DGtal 0.3.0

Board.cpp

Go to the documentation of this file.
00001 /* -*- mode: c++ -*- */
00010 /*
00011  * \@copyright This File is part of the Board library which is
00012  * licensed under the terms of the GNU Lesser General Public Licence.
00013  * See the LICENCE file for further details.
00014  */
00015 
00016 #include "Board.h"
00017 #include "Board/Point.h"
00018 #include "Board/Rect.h"
00019 #include "Board/Shapes.h"
00020 #include "Board/Tools.h"
00021 #include "Board/PSFonts.h"
00022 #include <fstream>
00023 #include <iostream>
00024 #include <iomanip>
00025 #include <typeinfo>
00026 #include <ctime>
00027 #include <cstring>
00028 #include <map>
00029 #include <algorithm>
00030 #include <cstdio>
00031 #include <algorithm>
00032 
00033 #if defined( max )
00034 #undef max
00035 #endif
00036 
00037 namespace {
00038   const float pageSizes[3][2] = { { 0.0f, 0.0f }, // BoundingBox
00039                                   { 210.0f, 297.0f },
00040                                   { 8.5f*25.4f, 11.0f*25.4f } };
00041   const float ppmm = 720.0f / 254.0f;
00042 }
00043 
00044 namespace LibBoard {
00045 
00046 const double Board::Degree =  3.14159265358979323846 / 180.0;
00047 
00048 Board::State::State()
00049 {
00050   penColor = Color::Black;
00051   fillColor =  Color::None;
00052   lineWidth = 0.5;
00053   lineStyle = Shape::SolidStyle;
00054   lineCap = Shape::ButtCap;
00055   lineJoin = Shape::MiterJoin;
00056   font = Fonts::TimesRoman;
00057   fontSize = 11.0;
00058   unitFactor = 1.0;
00059 }
00060 
00061 Board::Board( const Color & bgColor )
00062   : _backgroundColor( bgColor )
00063 {
00064 }
00065 
00066 Board::Board( const Board & other )
00067   : ShapeList( other ),
00068     _state( other._state ),
00069     _backgroundColor( other._backgroundColor )
00070 {
00071 }
00072 
00073 Board &
00074 Board::operator=( const Board & other )
00075 {
00076   free();
00077   if ( ! other._shapes.size() ) return (*this);  
00078   _shapes.resize( other._shapes.size(), 0 );
00079   std::vector<Shape*>::iterator t = _shapes.begin();
00080   std::vector<Shape*>::const_iterator i = other._shapes.begin();
00081   std::vector<Shape*>::const_iterator end = other._shapes.end();
00082   while ( i != end ) {
00083     *t = (*i)->clone();
00084     ++i; ++t;
00085   }
00086   return *this;
00087 }
00088 
00089 Board &
00090 Board::operator<<( const Shape & shape )
00091 {
00092   ShapeList::addShape( shape, _state.unitFactor );
00093   return *this;
00094 }
00095 
00096 Board &
00097 Board::operator<<( Unit unit )
00098 {
00099   setUnit( unit );
00100   return *this;
00101 }
00102 
00103 Board::~Board()
00104 {
00105 
00106 }
00107 
00108 void
00109 Board::clear( const Color & color )
00110 {
00111   ShapeList::clear();
00112   _backgroundColor = color;
00113 }
00114 
00115 
00116 Shape &
00117 Board::rotate( double angle, const Point & aCenter )
00118 {
00119   ShapeList::rotate( angle, aCenter );
00120   _clippingPath.rotate( angle, aCenter );
00121   return (*this);
00122 }
00123 
00124 Shape &
00125 Board::rotate( double angle )
00126 {
00127   ShapeList::rotate( angle );
00128   _clippingPath.rotate( angle, center() );
00129   return (*this);
00130 }
00131 
00132 Shape &
00133 Board::translate( double dx, double dy )
00134 {
00135   ShapeList::translate( dx, dy );
00136   _clippingPath.translate( dx, dy );
00137   return (*this);
00138 }
00139 
00140 Shape &
00141 Board::scale( double sx, double sy )
00142 {
00143   Point delta = _clippingPath.center() - center();
00144   delta.x *= sx;
00145   delta.y *= sy;
00146   _clippingPath.scale( sx, sy );
00147   ShapeList::scale( sx, sy );
00148   delta = ( center() + delta ) - _clippingPath.center();
00149   _clippingPath.translate( delta.x, delta.y );
00150   return (*this);
00151 }
00152 
00153 Shape &
00154 Board::scale( double s )
00155 {
00156   Point delta = _clippingPath.center() - center();
00157   delta *= s;
00158   _clippingPath.scale( s );
00159   ShapeList::scale( s );
00160   delta = ( center() + delta ) - _clippingPath.center();
00161   _clippingPath.translate( delta.x, delta.y );
00162   return (*this);
00163 }
00164 
00165 Board
00166 Board::rotated( double angle, const Point & aCenter )
00167 {
00168   return static_cast<const Board &>( Board( *this ).rotate( angle, aCenter ) );
00169 }
00170 
00171 Board
00172 Board::rotated( double angle )
00173 {
00174   return static_cast<const Board &>( Board( *this ).rotate( angle ) );
00175 }
00176 
00177 Board
00178 Board::translated( double dx, double dy )
00179 {
00180   return static_cast<const Board &>( Board( *this ).translate( dx, dy ) );
00181 }
00182 
00183 Board
00184 Board::scaled( double sx, double sy )
00185 {
00186   return static_cast<const Board &>( Board( *this ).scale( sx, sy ) );
00187 }
00188 
00189 Board
00190 Board::scaled( double s )
00191 {
00192   return static_cast<const Board &>( Board( *this ).scale( s ) );
00193 }
00194 
00195 
00196 void
00197 Board::setUnit( Unit unit )
00198 {
00199   switch ( unit ) {
00200   case UPoint:
00201     _state.unitFactor = 1.0;
00202     break;
00203   case UInche:
00204     _state.unitFactor = 25.4f * ppmm;
00205     break;
00206   case UCentimeter:
00207     _state.unitFactor = 10.0f * ppmm;
00208     break;
00209   case UMillimeter:
00210     _state.unitFactor = ppmm;
00211     break;
00212   }
00213 }
00214 
00215 void
00216 Board::setUnit( double factor, Unit unit )
00217 {
00218   switch ( unit ) {
00219   case UPoint:
00220     _state.unitFactor = factor;
00221     break;
00222   case UInche:
00223     _state.unitFactor = 720.0f * factor;
00224     break;
00225   case UCentimeter:
00226     _state.unitFactor = 10.0f * ppmm * factor;
00227     break;
00228   case UMillimeter:
00229     _state.unitFactor = ppmm * factor;
00230     break;
00231   }
00232 }
00233 
00234 Board &
00235 Board::setPenColorRGBi( unsigned char red,
00236                         unsigned char green,
00237                         unsigned char blue, 
00238                         unsigned char alpha )
00239 {
00240   _state.penColor.setRGBi( red, green, blue, alpha );
00241   return *this;
00242 }
00243 
00244 Board &
00245 Board::setPenColorRGBf(  float red,
00246                          float green,
00247                          float blue, 
00248                          float alpha )
00249 {
00250   _state.penColor.setRGBf( red, green, blue, alpha );
00251   return *this;
00252 }
00253 
00254 Board &
00255 Board::setPenColor( const Color & color )
00256 {
00257   _state.penColor = color;
00258   return *this;
00259 }
00260 
00261 Board &
00262 Board::setFillColorRGBi( unsigned char red,
00263                          unsigned char green,
00264                          unsigned char blue,
00265                          unsigned char alpha )
00266 {
00267   _state.fillColor.setRGBi( red, green, blue, alpha );
00268   return *this;
00269 }
00270 
00271 Board &
00272 Board::setFillColorRGBf( float red, float green, float blue, float alpha )
00273 {
00274   _state.fillColor.setRGBf( red, green, blue, alpha );
00275   return *this;
00276 }
00277 
00278 Board &
00279 Board::setFillColor( const Color & color )
00280 {
00281   _state.fillColor = color;
00282   return *this;
00283 }
00284 
00285 Board &
00286 Board::setLineWidth( double width )
00287 {
00288   _state.lineWidth = width;
00289   return *this;
00290 }
00291 
00292 Board &
00293 Board::setFont( const Fonts::Font font, double fontSize )
00294 {
00295   _state.font = font;
00296   _state.fontSize = fontSize;
00297   return *this;
00298 }
00299 
00300 Board &
00301 Board::setFontSize( double fontSize )
00302 {
00303   _state.fontSize = fontSize;
00304   return *this;
00305 }
00306 
00307 void
00308 Board::backgroundColor( const Color & color )
00309 {
00310   _backgroundColor = color;
00311 }
00312 
00313 void
00314 Board::drawDot( double x, double y, int depthValue )
00315 {  
00316   if ( depthValue != -1 ) 
00317     _shapes.push_back( new Dot( _state.unit(x), _state.unit(y),
00318                                 _state.penColor, _state.lineWidth, depthValue ) );
00319   else
00320     _shapes.push_back( new Dot( _state.unit(x), _state.unit(y),
00321                                 _state.penColor, _state.lineWidth, _nextDepth-- ) );
00322 }
00323 
00324 void
00325 Board::drawLine( double x1, double y1, double x2, double y2, 
00326                  int depthValue /* = -1 */  )
00327 {
00328   if ( depthValue != -1 ) 
00329     _shapes.push_back( new Line( _state.unit(x1), _state.unit(y1),
00330                                  _state.unit(x2), _state.unit(y2),
00331                                  _state.penColor, _state.lineWidth,
00332                                  _state.lineStyle, _state.lineCap, _state.lineJoin, depthValue ) );
00333   else
00334     _shapes.push_back( new Line( _state.unit(x1), _state.unit(y1),
00335                                  _state.unit(x2), _state.unit(y2),
00336                                  _state.penColor, _state.lineWidth,
00337                                  _state.lineStyle, _state.lineCap, _state.lineJoin, _nextDepth-- ) );
00338 }
00339 
00340 void
00341 Board::drawArrow( double x1, double y1, double x2, double y2, 
00342                   bool filledArrow /* = false */,
00343                   int depthValue /* = -1 */  )
00344 {
00345   if ( depthValue != -1 )
00346     _shapes.push_back( new Arrow( _state.unit(x1), _state.unit(y1),
00347                                   _state.unit(x2), _state.unit(y2),
00348                                   _state.penColor, filledArrow ? _state.penColor : Color::None,
00349                                   _state.lineWidth, _state.lineStyle, _state.lineCap, _state.lineJoin, depthValue ) );
00350   else
00351     _shapes.push_back( new Arrow( _state.unit(x1), _state.unit(y1),
00352                                   _state.unit(x2), _state.unit(y2),
00353                                   _state.penColor, filledArrow ? _state.penColor : Color::None,
00354                                   _state.lineWidth, _state.lineStyle, _state.lineCap, _state.lineJoin, _nextDepth-- ) );
00355 }
00356 
00357 void
00358 Board::drawRectangle( double x, double y, 
00359                       double width, double height,
00360                       int depthValue /* = -1 */ )
00361 {
00362   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00363   _shapes.push_back( new Rectangle( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height), 
00364                                     _state.penColor, _state.fillColor,
00365                                     _state.lineWidth, _state.lineStyle, _state.lineCap, _state.lineJoin, d ) );
00366 }
00367 
00368 void
00369 Board::drawImage(std::string filename, double x, double y, 
00370                  double width, double height,
00371                  int depthValue /* = -1 */ )
00372 {
00373   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00374   _shapes.push_back( new Image( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height), 
00375                                 filename, d ) );
00376 }
00377 
00378 
00379 void
00380 Board::fillRectangle( double x, double y,
00381                       double width, double height,
00382                       int depthValue /* = -1 */ )
00383 {
00384   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00385   _shapes.push_back( new Rectangle( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height),
00386                                     Color::None, _state.penColor,
00387                                     0.0f, _state.lineStyle, _state.lineCap, _state.lineJoin,
00388                                     d ) );
00389 }
00390 
00391 void
00392 Board::drawCircle( double x, double y, double radius,
00393                    int depthValue /* = -1 */  )
00394 {
00395   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00396   _shapes.push_back( new Circle( _state.unit(x), _state.unit(y), _state.unit(radius), 
00397                                  _state.penColor, _state.fillColor,
00398                                  _state.lineWidth, _state.lineStyle, d ) );
00399 }
00400 
00401 void
00402 Board::fillCircle( double x, double y,
00403                    double radius,
00404                    int depthValue /* = -1 */ )
00405 {
00406   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00407   _shapes.push_back( new Circle( _state.unit(x), _state.unit(y), _state.unit(radius), 
00408                                  Color::None, _state.penColor,
00409                                  0.0f, _state.lineStyle, d ) );
00410 }
00411 
00412 void
00413 Board::drawEllipse( double x, double y,
00414                     double xRadius, double yRadius,
00415                     int depthValue /* = -1 */  )
00416 {
00417   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00418   _shapes.push_back( new Ellipse( _state.unit(x), _state.unit(y),
00419                                   _state.unit(xRadius), _state.unit(yRadius),
00420                                   _state.penColor,
00421                                   _state.fillColor,
00422                                   _state.lineWidth,
00423                                   _state.lineStyle,
00424                                   d ) );
00425 }
00426 
00427 void
00428 Board::fillEllipse( double x, double y, 
00429                     double xRadius, double yRadius,
00430                     int depthValue /* = -1 */ )
00431 {
00432   int d = depthValue ? depthValue : _nextDepth--;
00433   _shapes.push_back( new Ellipse( _state.unit(x), _state.unit(y), _state.unit(xRadius), _state.unit(yRadius),
00434                                   Color::None,
00435                                   _state.penColor,
00436                                   0.0f, 
00437                                   _state.lineStyle,
00438                                   d ) );
00439 }
00440 
00441 void
00442 Board::drawPolyline( const std::vector<Point> & points,
00443                      int depthValue /* = -1 */ )
00444 {
00445   int d = (depthValue != -1) ? depthValue : _nextDepth--;  
00446   std::vector<Point> v = points;
00447   std::vector<Point>::iterator it = v.begin();
00448   std::vector<Point>::iterator end = v.end();
00449   while ( it != end ) {
00450     (*it) = _state.unit( *it );
00451     ++it;
00452   }
00453   _shapes.push_back( new Polyline( v, false, _state.penColor, _state.fillColor,
00454                                    _state.lineWidth,
00455                                    _state.lineStyle,
00456                                    _state.lineCap,
00457                                    _state.lineJoin,
00458                                    d ) );
00459 }
00460 
00461 void
00462 Board::drawClosedPolyline( const std::vector<Point> & points,
00463                            int depthValue /* = -1 */ )
00464 {
00465   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00466   std::vector<Point> v = points;
00467   std::vector<Point>::iterator it = v.begin();
00468   std::vector<Point>::iterator end = v.end();
00469   while ( it != end ) {
00470     (*it) = _state.unit( *it );
00471     ++it;
00472   }
00473   _shapes.push_back( new Polyline( v, true, _state.penColor, _state.fillColor,
00474                                    _state.lineWidth,
00475                                    _state.lineStyle,
00476                                    _state.lineCap,
00477                                    _state.lineJoin,
00478                                    d ) );
00479 }
00480 
00481 void
00482 Board::fillPolyline( const std::vector<Point> & points,
00483                      int depthValue /* = -1 */ )
00484 {
00485   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00486   _shapes.push_back( new Polyline( points, true, Color::None, _state.penColor,
00487                                    0.0f,
00488                                    _state.lineStyle,
00489                                    _state.lineCap,
00490                                    _state.lineJoin,
00491                                    d ) );
00492 }
00493 
00494 void
00495 Board::drawTriangle( double x1, double y1, 
00496                      double x2, double y2, 
00497                      double x3, double y3, 
00498                      int depthValue /* = -1 */ )
00499 {
00500   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00501   std::vector<Point> points;
00502   points.push_back( Point( _state.unit(x1), _state.unit(y1) ) );
00503   points.push_back( Point( _state.unit(x2), _state.unit(y2) ) );
00504   points.push_back( Point( _state.unit(x3), _state.unit(y3) ) );
00505   _shapes.push_back( new Polyline( points, true, _state.penColor, _state.fillColor,
00506                                    _state.lineWidth,
00507                                    _state.lineStyle,
00508                                    _state.lineCap,
00509                                    _state.lineJoin,
00510                                    d ) );
00511 }
00512 
00513 void
00514 Board::drawTriangle( const Point & p1,
00515                      const Point & p2, 
00516                      const Point & p3, 
00517                      int depthValue /* = -1 */ )
00518 {
00519   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00520   std::vector<Point> points;
00521   points.push_back( Point( _state.unit(p1.x), _state.unit(p1.y) ) );
00522   points.push_back( Point( _state.unit(p2.x), _state.unit(p2.y) ) );
00523   points.push_back( Point( _state.unit(p3.x), _state.unit(p3.y) ) );
00524   _shapes.push_back( new Polyline( points, true, _state.penColor, _state.fillColor,
00525                                    _state.lineWidth,
00526                                    _state.lineStyle,
00527                                    _state.lineCap,
00528                                    _state.lineJoin,
00529                                    d ) );  
00530 }
00531 
00532 void
00533 Board::fillTriangle( double x1, double y1, 
00534                      double x2, double y2, 
00535                      double x3, double y3, 
00536                      int depthValue /* = -1 */ )
00537 {
00538   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00539   std::vector<Point> points;
00540   points.push_back( Point( _state.unit(x1), _state.unit(y1) ) );
00541   points.push_back( Point( _state.unit(x2), _state.unit(y2) ) );
00542   points.push_back( Point( _state.unit(x3), _state.unit(y3) ) );
00543   _shapes.push_back( new Polyline( points, true, Color::None, _state.penColor,
00544                                    0.0f,
00545                                    _state.lineStyle,
00546                                    _state.lineCap,
00547                                    _state.lineJoin,
00548                                    d ) );
00549 }
00550 
00551 void
00552 Board::fillTriangle( const Point & p1,
00553                      const Point & p2, 
00554                      const Point & p3, 
00555                      int depthValue /* = -1 */ )
00556 {
00557   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00558   std::vector<Point> points;
00559   points.push_back( Point( _state.unit(p1.x), _state.unit(p1.y) ) );
00560   points.push_back( Point( _state.unit(p2.x), _state.unit(p2.y) ) );
00561   points.push_back( Point( _state.unit(p3.x), _state.unit(p3.y) ) );
00562   _shapes.push_back( new Polyline( points, true, Color::None, _state.penColor,
00563                                    0.0f,
00564                                    _state.lineStyle,
00565                                    _state.lineCap,
00566                                    _state.lineJoin,
00567                                    d ) );  
00568 }
00569 
00570 void
00571 Board::fillGouraudTriangle( const Point & p1,
00572                             const Color & color1,
00573                             const Point & p2,
00574                             const Color & color2,
00575                             const Point & p3,
00576                             const Color & color3,
00577                             unsigned char divisions,
00578                             int depthValue /* = -1 */ )
00579 {
00580   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00581   _shapes.push_back( new GouraudTriangle( Point( _state.unit(p1.x), _state.unit(p1.y) ), color1,
00582                                           Point( _state.unit(p2.x), _state.unit(p2.y) ), color2,
00583                                           Point( _state.unit(p3.x), _state.unit(p3.y) ), color3,
00584                                           divisions, d ) );
00585 }
00586 
00587 void
00588 Board::fillGouraudTriangle( const Point & p1,
00589                             const float brightness1,
00590                             const Point & p2,
00591                             const float brightness2,
00592                             const Point & p3,
00593                             const float brightness3,
00594                             unsigned char divisions,
00595                             int depthValue /* = -1 */ )
00596 {
00597   Color color1( _state.penColor );
00598   Color color2( _state.penColor );
00599   Color color3( _state.penColor );
00600   color1.red( static_cast<unsigned char>( std::min( 255.0f, color1.red() * brightness1 ) ) );
00601   color1.green( static_cast<unsigned char>( std::min( 255.0f, color1.green() * brightness1 ) ) );
00602   color1.blue( static_cast<unsigned char>( std::min( 255.0f, color1.blue() * brightness1 ) ) );
00603   color2.red( static_cast<unsigned char>( std::min( 255.0f, color2.red() * brightness2 ) ) );
00604   color2.green( static_cast<unsigned char>( std::min( 255.0f, color2.green() * brightness2 ) ) );
00605   color2.blue( static_cast<unsigned char>( std::min( 255.0f, color2.blue() * brightness2 ) ) );
00606   color3.red( static_cast<unsigned char>( std::min( 255.0f, color3.red() * brightness3 ) ) );
00607   color3.green( static_cast<unsigned char>( std::min( 255.0f, color3.green() * brightness3 ) ) );
00608   color3.blue( static_cast<unsigned char>( std::min( 255.0f, color3.blue() * brightness3 ) ) );
00609   fillGouraudTriangle( Point( _state.unit(p1.x), _state.unit(p1.y) ), color1,
00610                        Point( _state.unit(p2.x), _state.unit(p2.y) ), color2,
00611                        Point( _state.unit(p3.x), _state.unit(p3.y) ), color3,
00612                        divisions,
00613                        depthValue );
00614 }
00615 
00616 void
00617 Board::drawText( double x, double y, const char * text,
00618                  int depthValue /* = -1 */ )
00619 {
00620   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00621   _shapes.push_back( new Text( _state.unit(x), _state.unit(y), text,
00622                                _state.font, _state.fontSize, _state.penColor, d ) );
00623 }
00624 
00625 void
00626 Board::drawText( double x, double y, const std::string & str, int depthValue /* = -1 */ )
00627 {
00628   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00629   _shapes.push_back( new Text( _state.unit(x), _state.unit(y), str,
00630                                _state.font, _state.fontSize, _state.penColor, d ) );
00631 }
00632 
00633 void
00634 Board::drawBoundingBox( int depthValue /* = -1 */ )
00635 {
00636   int d = (depthValue != -1) ? depthValue : _nextDepth--;
00637   Rect box = boundingBox();
00638   _shapes.push_back( new Rectangle( _state.unit(box.left),
00639                                     _state.unit(box.top),
00640                                     _state.unit(box.width),
00641                                     _state.unit(box.height),
00642                                     _state.penColor,
00643                                     _state.fillColor,
00644                                     _state.lineWidth,
00645                                     _state.lineStyle,
00646                                     _state.lineCap,
00647                                     _state.lineJoin,
00648                                     d ) );
00649 }
00650 
00651 void
00652 Board::setClippingRectangle( double xLeft, double yTop, 
00653                              double rectWidth, double rectHeight )
00654 {
00655   _clippingPath.clear();
00656   _clippingPath << _state.unit( Point( xLeft, yTop ) );
00657   _clippingPath << _state.unit( Point( xLeft + rectWidth, yTop ) );
00658   _clippingPath << _state.unit( Point( xLeft + rectWidth, yTop - rectHeight) );
00659   _clippingPath << _state.unit( Point( xLeft , yTop - rectHeight ) );
00660 }
00661 
00662 void
00663 Board::setClippingPath(  const std::vector<Point> & points  )
00664 {
00665   _clippingPath.clear();
00666   std::vector<Point>::const_iterator it = points.begin();
00667   std::vector<Point>::const_iterator end = points.end();
00668   while ( it != end ) {
00669     _clippingPath << _state.unit( *it );
00670     ++it;
00671   }
00672 }
00673 
00674 void
00675 Board::setClippingPath(  const Path & path  )
00676 {
00677   _clippingPath = path;
00678   _clippingPath.setClosed( true );
00679   if ( _clippingPath.size() > 1 ) {
00680     if ( _clippingPath[0] == _clippingPath[ _clippingPath.size() - 1 ] ) 
00681       _clippingPath.pop_back();
00682   }
00683   unsigned int n = _clippingPath.size();
00684   for ( unsigned int i = 0; i < n; ++i ) {
00685     _clippingPath[i] = _state.unit( _clippingPath[i] );
00686   }
00687 }
00688 
00689 
00690 void
00691 Board::addDuplicates( const Shape & shape,
00692                       unsigned int times,
00693                       double dx, double dy, double scaleValue )
00694 {
00695   Shape * s = shape.clone();
00696   while ( times-- ) {
00697     (*this) << (*s);
00698     if ( scaleValue != 1.0 )
00699       s->scale( scaleValue );
00700     s->translate( dx, dy );
00701   }
00702   delete s;
00703 }
00704 
00705 void
00706 Board::addDuplicates( const Shape & shape,
00707                       unsigned int times,
00708                       double dx, double dy,
00709                       double scaleX, double scaleY,
00710                       double angle )
00711 {
00712   Shape * s = shape.clone();
00713   while ( times-- ) {
00714     (*this) << (*s);
00715     if ( scaleX != 1.0 || scaleY != 1.0 ) s->scale( scaleX, scaleY );
00716     if ( dx != 0.0 || dy != 0.0 ) s->translate( dx, dy );
00717     if ( angle != 0.0 ) s->rotate( angle );
00718   }
00719   delete s;
00720 }
00721 
00722 void
00723 Board::saveEPS( const char * filename, PageSize size, double margin ) const
00724 {
00725   saveEPS( filename, pageSizes[size][0], pageSizes[size][1], margin );
00726 }
00727   
00728 void
00729 Board::saveEPS( const char * filename, double pageWidth, double pageHeight, double margin ) const
00730 {
00731   std::ofstream file( filename );
00732   Rect box = boundingBox();
00733   bool clipping = _clippingPath.size() > 2;
00734   if ( clipping )
00735     box = box && _clippingPath.boundingBox();
00736   
00737   TransformEPS transform;
00738   transform.setBoundingBox( box, pageWidth, pageHeight, margin );
00739   
00740   file << "%!PS-Adobe-2.0 EPSF-2.0" << std::endl;
00741   file << "%%Title: " << filename << std::endl;
00742   file << "%%Creator: Board library (Copyleft)2007 Sebastien Fourey" << std::endl;
00743   {
00744     time_t t = time(0);
00745     char str_time[255];
00746     secured_ctime( str_time, &t, 255 );
00747     file << "%%CreationDate: " << str_time;
00748   }
00749   file << "%%BoundingBox: " << std::setprecision( 8 )
00750        << transform.mapX( box.left ) << " "
00751        << transform.mapY( box.top - box.height ) << " "
00752        << transform.mapX( box.left + box.width ) << " "
00753        << transform.mapY( box.top ) << std::endl;
00754 
00755   file << "%Magnification: 1.0000" << std::endl;
00756   file << "%%EndComments" << std::endl;
00757 
00758   file << std::endl;
00759   file << "/cp {closepath} bind def" << std::endl;
00760   file << "/ef {eofill} bind def" << std::endl;
00761   file << "/gr {grestore} bind def" << std::endl;
00762   file << "/gs {gsave} bind def" << std::endl;
00763   file << "/sa {save} bind def" << std::endl;
00764   file << "/rs {restore} bind def" << std::endl;
00765   file << "/l {lineto} bind def" << std::endl;
00766   file << "/m {moveto} bind def" << std::endl;
00767   file << "/rm {rmoveto} bind def" << std::endl;
00768   file << "/n {newpath} bind def" << std::endl;
00769   file << "/s {stroke} bind def" << std::endl;
00770   file << "/sh {show} bind def" << std::endl;
00771   file << "/slc {setlinecap} bind def" << std::endl;
00772   file << "/slj {setlinejoin} bind def" << std::endl;
00773   file << "/slw {setlinewidth} bind def" << std::endl;
00774   file << "/srgb {setrgbcolor} bind def" << std::endl;
00775   file << "/rot {rotate} bind def" << std::endl;
00776   file << "/sc {scale} bind def" << std::endl;
00777   file << "/sd {setdash} bind def" << std::endl;
00778   file << "/ff {findfont} bind def" << std::endl;
00779   file << "/sf {setfont} bind def" << std::endl;
00780   file << "/scf {scalefont} bind def" << std::endl;
00781   file << "/sw {stringwidth} bind def" << std::endl;
00782   file << "/sd {setdash} bind def" << std::endl;
00783   file << "/tr {translate} bind def" << std::endl;
00784   file << " 0.5 setlinewidth" << std::endl;
00785 
00786   if ( clipping ) {
00787     file << " newpath ";
00788     _clippingPath.flushPostscript( file, transform );
00789     file << " 0 slw clip " << std::endl;
00790   }
00791   
00792   // Draw the background color if needed.
00793   if ( _backgroundColor != Color::None ) { 
00794     Rectangle r( box, Color::None, _backgroundColor, 0.0f );
00795     r.flushPostscript( file, transform );
00796   }
00797 
00798   // Draw the shapes
00799   std::vector< Shape* > shapes = _shapes;
00800 
00801   stable_sort( shapes.begin(), shapes.end(), shapeGreaterDepth );
00802   std::vector< Shape* >::const_iterator i = shapes.begin();
00803   std::vector< Shape* >::const_iterator end = shapes.end();
00804 
00805   while ( i != end ) {
00806     (*i)->flushPostscript( file, transform );
00807     ++i;
00808   }
00809   file << "showpage" << std::endl;
00810   file << "%%Trailer" << std::endl;
00811   file << "%EOF" << std::endl;
00812   file.close();
00813 }
00814 
00815 void
00816 Board::saveFIG( const char * filename, PageSize size, double margin ) const
00817 {
00818   saveFIG( filename, pageSizes[size][0], pageSizes[size][1], margin );
00819 }
00820 
00821 void
00822 Board::saveFIG( const char * filename, double pageWidth, double pageHeight, double margin ) const
00823 {
00824   std::ofstream file( filename );
00825   TransformFIG transform;
00826   Rect box = boundingBox();
00827   transform.setBoundingBox( box, pageWidth, pageHeight, margin  );
00828   transform.setDepthRange( *this );
00829   
00830   file << "#FIG 3.2  Produced by the Board library (Copyleft)2007 Sebastien Fourey\n";
00831   file << "Portrait\n";
00832   file << "Center\n";
00833   file << "Metric\n";
00834   file << "A4\n";
00835   file << "100.00\n";
00836   file << "Single\n";
00837   file << "-2\n";
00838   file << "1200 2\n";
00839 
00840   std::map<Color,int> colormap;
00841   int maxColor = 32;
00842 
00843 
00844   colormap[Color(0,0,0)] = 0; 
00845   colormap[Color(0,0,255)] = 1; 
00846   colormap[Color(0,255,0)] = 2; 
00847   colormap[Color(0,255,255)] = 0; 
00848   colormap[Color(255,0,0)] = 4; 
00849   colormap[Color(255,0,255)] = 0; 
00850   colormap[Color(255,255,0)] = 6; 
00851   colormap[Color(255,255,255)] = 7;
00852 
00853 
00854   std::vector< Shape* > shapes = _shapes;
00855   stable_sort( shapes.begin(), shapes.end(), shapeGreaterDepth );
00856   std::vector< Shape* >::const_iterator i = shapes.begin();
00857   std::vector< Shape* >::const_iterator end = shapes.end();
00858   while ( i != end ) { 
00859     if ( colormap.find( (*i)->penColor() ) == colormap.end() 
00860          && (*i)->penColor().valid() )
00861       colormap[ (*i)->penColor() ] = maxColor++;
00862     if ( colormap.find( (*i)->fillColor() ) == colormap.end()
00863          && (*i)->fillColor().valid() )
00864       colormap[ (*i)->fillColor() ] = maxColor++;
00865     ++i;
00866   }
00867 
00868   if ( colormap.find( _backgroundColor ) == colormap.end()
00869        && _backgroundColor.valid() )
00870     colormap[ _backgroundColor ] = maxColor++;
00871   
00872   // Write the colormap
00873   std::map<Color,int>::const_iterator iColormap = colormap.begin();
00874   std::map<Color,int>::const_iterator endColormap = colormap.end();
00875   char colorString[255];
00876   while ( iColormap != endColormap ) {
00877     secured_sprintf( colorString, 255,
00878                              "0 %d #%02x%02x%02x\n",
00879                              iColormap->second,
00880                          iColormap->first.red(),
00881                          iColormap->first.green(),
00882                          iColormap->first.blue() );
00883     if ( iColormap->second >= 32 ) file << colorString;
00884     ++iColormap;
00885   }
00886 
00887   // Draw the background color if needed.
00888   if ( _backgroundColor != Color::None ) { 
00889     Rectangle r( box, Color::None, _backgroundColor, 0.0f );
00890     r.depth( std::numeric_limits<int>::max() );
00891     r.flushFIG( file, transform, colormap );
00892   }
00893 
00894   // Draw the shapes.
00895   i = shapes.begin();
00896   while ( i != end ) {
00897     // notice << (*i)->name() << " " << (*i)->depth() <<  '\n';
00898     (*i)->flushFIG( file, transform, colormap );
00899     ++i;
00900   }  
00901   file.close();
00902 }
00903 
00904 void
00905 Board::saveSVG( const char * filename, PageSize size, double margin ) const
00906 {
00907   saveSVG( filename, pageSizes[size][0], pageSizes[size][1], margin );
00908 }
00909 
00910 void
00911 Board::saveSVG( const char * filename, double pageWidth, double pageHeight, double margin ) const
00912 {
00913   std::ofstream file( filename );
00914   TransformSVG transform;
00915   Rect box = boundingBox();
00916   bool clipping = _clippingPath.size() > 2;
00917   if ( clipping )
00918     box = box && _clippingPath.boundingBox();
00919   transform.setBoundingBox( box, pageWidth, pageHeight, margin );
00920 
00921   file << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" << std::endl;
00922   file << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"" << std::endl;
00923   file << " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" << std::endl;
00924 
00925   if ( pageWidth > 0 && pageHeight > 0 ) {
00926     file << "<svg width=\""
00927          << pageWidth << "mm\" height=\""
00928          << pageHeight << "mm\" " << std::endl;
00929     file << "     viewBox=\"0 0 "
00930          << pageWidth * ppmm  << " "
00931          << pageHeight * ppmm  << "\" " << std::endl;
00932     file << "     xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" >" << std::endl;
00933   } else {
00934     file << "<svg width=\""
00935          << ( box.width / ppmm )  << "mm"
00936          << "\" height=\""
00937          << ( box.height / ppmm ) << "mm"
00938          << "\" " << std::endl;
00939     file << "     viewBox=\"0 0 "
00940          << box.width  << " "
00941          << box.height << "\" " << std::endl;
00942     file << "     xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" >" << std::endl;
00943 
00944   }
00945 
00946   file << "<desc>" << filename 
00947        << ", created with the Board library (Copyleft) 2007 Sebastien Fourey" 
00948        << "</desc>" << std::endl;
00949 
00950   if ( clipping  ) {
00951     file << "<g clip-rule=\"nonzero\">\n"
00952          << " <clipPath id=\"GlobalClipPath\">\n"
00953          << "  <path clip-rule=\"evenodd\"  d=\"";
00954     _clippingPath.flushSVGCommands( file, transform );
00955     file << "\" />\n";
00956     file << " </clipPath>\n";
00957     file << "<g clip-path=\"url(#GlobalClipPath)\">\n";
00958   }
00959   
00960   // Draw the background color if needed.
00961   if ( _backgroundColor != Color::None ) { 
00962     Rectangle r( box, Color::None, _backgroundColor, 0.0 );
00963     r.flushSVG( file, transform );
00964   }
00965   
00966   // Draw the shapes.
00967   std::vector< Shape* > shapes = _shapes;
00968   stable_sort( shapes.begin(), shapes.end(), shapeGreaterDepth );
00969   std::vector< Shape* >::const_iterator i = shapes.begin();
00970   std::vector< Shape* >::const_iterator end = shapes.end();
00971   while ( i != end ) {
00972     (*i)->flushSVG( file, transform );
00973     ++i;
00974   }  
00975 
00976   if ( clipping )
00977     file << "</g>\n</g>";
00978   file << "</svg>" << std::endl;
00979   file.close();
00980 }
00981 
00982 void
00983 Board::save( const char * filename, double pageWidth, double pageHeight, double margin ) const 
00984 {
00985   const char * extension = filename + strlen( filename );
00986   while ( extension > filename && *extension != '.' ) 
00987     --extension;
00988   if ( !(strcmp( extension, ".eps" )) || !(strcmp( extension, ".EPS" )) ) {
00989     saveEPS( filename, pageWidth, pageHeight, margin );
00990     return;
00991   }
00992   if ( !(strcmp( extension, ".fig" )) || !(strcmp( extension, ".FIG" )) ) {
00993     saveFIG( filename, pageWidth, pageHeight, margin );
00994     return;
00995   }
00996   if ( !(strcmp( extension, ".svg" )) || !(strcmp( extension, ".SVG" )) ) {
00997     saveSVG( filename, pageWidth, pageHeight, margin );
00998     return;
00999   }
01000 }
01001 
01002 void
01003 Board::save( const char * filename, PageSize size, double margin ) const 
01004 {
01005   save( filename, pageSizes[size][0], pageSizes[size][1], margin );
01006 }
01007 
01008 } // namespace LibBoard;
01009 
01010 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines