18 #include "Board/Point.h"
19 #include "Board/Rect.h"
20 #include "Board/Shapes.h"
21 #include "Board/Tools.h"
22 #include "Board/PSFonts.h"
36 #include <cairo-pdf.h>
38 #include <cairo-svg.h>
44 #define _USE_MATH_DEFINES
58 #pragma warning(disable : 4290)
64 #define _HAS_MSVC_MAX_ true
68 #define _HAS_MSVC_MIN_ true
74 const float pageSizes[3][2] = { { 0.0f, 0.0f },
76 { 8.5f*25.4f, 11.0f*25.4f } };
77 const float ppmm = 720.0f / 254.0f;
102 Board::Board(
const Board & other )
103 : ShapeList( other ),
104 _state( other._state ),
105 _backgroundColor( other._backgroundColor )
110 Board::operator=(
const Board & other )
113 if ( ! other._shapes.size() )
return (*
this);
114 _shapes.resize( other._shapes.size(), 0 );
115 std::vector<Shape*>::iterator t = _shapes.begin();
116 std::vector<Shape*>::const_iterator i = other._shapes.begin();
117 std::vector<Shape*>::const_iterator end = other._shapes.end();
128 ShapeList::addShape( shape, _state.unitFactor );
148 _backgroundColor = color;
153 Board::rotate(
double angle,
const Point & aCenter )
155 ShapeList::rotate( angle, aCenter );
156 _clippingPath.rotate( angle, aCenter );
161 Board::rotate(
double angle )
163 ShapeList::rotate( angle );
164 _clippingPath.rotate( angle, center() );
169 Board::translate(
double dx,
double dy )
171 ShapeList::translate( dx, dy );
172 _clippingPath.translate( dx, dy );
177 Board::scale(
double sx,
double sy )
179 Point delta = _clippingPath.center() - center();
182 _clippingPath.scale( sx, sy );
183 ShapeList::scale( sx, sy );
184 delta = ( center() + delta ) - _clippingPath.center();
185 _clippingPath.translate( delta.
x, delta.
y );
190 Board::scale(
double s )
192 Point delta = _clippingPath.center() - center();
194 _clippingPath.scale( s );
195 ShapeList::scale( s );
196 delta = ( center() + delta ) - _clippingPath.center();
197 _clippingPath.translate( delta.
x, delta.
y );
202 Board::rotated(
double angle,
const Point & aCenter )
204 return static_cast<const Board &
>( Board( *this ).rotate( angle, aCenter ) );
208 Board::rotated(
double angle )
210 return static_cast<const Board &
>( Board( *this ).rotate( angle ) );
214 Board::translated(
double dx,
double dy )
216 return static_cast<const Board &
>( Board( *this ).translate( dx, dy ) );
220 Board::scaled(
double sx,
double sy )
222 return static_cast<const Board &
>( Board( *this ).scale( sx, sy ) );
226 Board::scaled(
double s )
228 return static_cast<const Board &
>( Board( *this ).scale( s ) );
233 Board::setUnit( Unit unit )
237 _state.unitFactor = 1.0;
240 _state.unitFactor = 25.4f * ppmm;
243 _state.unitFactor = 10.0f * ppmm;
246 _state.unitFactor = ppmm;
252 Board::setUnit(
double factor, Unit unit )
256 _state.unitFactor = factor;
259 _state.unitFactor = 720.0f * factor;
262 _state.unitFactor = 10.0f * ppmm * factor;
265 _state.unitFactor = ppmm * factor;
271 Board::setPenColorRGBi(
unsigned char red,
274 unsigned char alpha )
276 _state.penColor.setRGBi( red, green, blue, alpha );
281 Board::setPenColorRGBf(
float red,
286 _state.penColor.setRGBf( red, green, blue, alpha );
293 _state.penColor = color;
298 Board::setFillColorRGBi(
unsigned char red,
301 unsigned char alpha )
303 _state.fillColor.
setRGBi( red, green, blue, alpha );
308 Board::setFillColorRGBf(
float red,
float green,
float blue,
float alpha )
310 _state.fillColor.
setRGBf( red, green, blue, alpha );
317 _state.fillColor = color;
322 Board::setLineWidth(
double width )
324 _state.lineWidth = width;
329 Board::setFont(
const Fonts::Font font,
double fontSize )
332 _state.fontSize = fontSize;
337 Board::setFontSize(
double fontSize )
339 _state.fontSize = fontSize;
346 _backgroundColor = color;
350 Board::drawDot(
double x,
double y,
int depthValue )
352 if ( depthValue != -1 )
353 _shapes.push_back(
new Dot( _state.unit(x), _state.unit(y),
354 _state.penColor, _state.lineWidth, depthValue ) );
356 _shapes.push_back(
new Dot( _state.unit(x), _state.unit(y),
357 _state.penColor, _state.lineWidth, _nextDepth-- ) );
361 Board::drawLine(
double x1,
double y1,
double x2,
double y2,
364 if ( depthValue != -1 )
365 _shapes.push_back(
new Line( _state.unit(x1), _state.unit(y1),
366 _state.unit(x2), _state.unit(y2),
367 _state.penColor, _state.lineWidth,
368 _state.lineStyle, _state.lineCap, _state.lineJoin, depthValue ) );
370 _shapes.push_back(
new Line( _state.unit(x1), _state.unit(y1),
371 _state.unit(x2), _state.unit(y2),
372 _state.penColor, _state.lineWidth,
373 _state.lineStyle, _state.lineCap, _state.lineJoin, _nextDepth-- ) );
377 Board::drawArrow(
double x1,
double y1,
double x2,
double y2,
381 if ( depthValue != -1 )
382 _shapes.push_back(
new Arrow( _state.unit(x1), _state.unit(y1),
383 _state.unit(x2), _state.unit(y2),
385 _state.lineWidth, _state.lineStyle, _state.lineCap, _state.lineJoin, depthValue ) );
387 _shapes.push_back(
new Arrow( _state.unit(x1), _state.unit(y1),
388 _state.unit(x2), _state.unit(y2),
390 _state.lineWidth, _state.lineStyle, _state.lineCap, _state.lineJoin, _nextDepth-- ) );
394 Board::drawRectangle(
double x,
double y,
395 double width,
double height,
398 int d = (depthValue != -1) ? depthValue : _nextDepth--;
399 _shapes.push_back(
new Rectangle( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height),
400 _state.penColor, _state.fillColor,
401 _state.lineWidth, _state.lineStyle, _state.lineCap, _state.lineJoin, d ) );
405 Board::drawImage(std::string filename,
double x,
double y,
406 double width,
double height,
407 int depthValue,
double alpha )
409 int d = (depthValue != -1) ? depthValue : _nextDepth--;
410 _shapes.push_back(
new Image( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height),
411 filename, d, alpha ) );
416 Board::fillRectangle(
double x,
double y,
417 double width,
double height,
420 int d = (depthValue != -1) ? depthValue : _nextDepth--;
421 _shapes.push_back(
new Rectangle( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height),
423 0.0f, _state.lineStyle, _state.lineCap, _state.lineJoin,
428 Board::drawCircle(
double x,
double y,
double radius,
431 int d = (depthValue != -1) ? depthValue : _nextDepth--;
432 _shapes.push_back(
new Circle( _state.unit(x), _state.unit(y), _state.unit(radius),
433 _state.penColor, _state.fillColor,
434 _state.lineWidth, _state.lineStyle, d ) );
438 Board::drawArc(
double x,
double y,
double radius,
double angle1,
double angle2,
439 bool neg,
int depthValue ){
440 int d = (depthValue != -1) ? depthValue : _nextDepth--;
441 _shapes.push_back(
new Arc( _state.unit(x), _state.unit(y), _state.unit(radius),
442 angle1, angle2, neg,_state.penColor,
448 Board::fillCircle(
double x,
double y,
452 int d = (depthValue != -1) ? depthValue : _nextDepth--;
453 _shapes.push_back(
new Circle( _state.unit(x), _state.unit(y), _state.unit(radius),
455 0.0f, _state.lineStyle, d ) );
459 Board::drawEllipse(
double x,
double y,
460 double xRadius,
double yRadius,
463 int d = (depthValue != -1) ? depthValue : _nextDepth--;
464 _shapes.push_back(
new Ellipse( _state.unit(x), _state.unit(y),
465 _state.unit(xRadius), _state.unit(yRadius),
474 Board::fillEllipse(
double x,
double y,
475 double xRadius,
double yRadius,
478 int d = depthValue ? depthValue : _nextDepth--;
479 _shapes.push_back(
new Ellipse( _state.unit(x), _state.unit(y), _state.unit(xRadius), _state.unit(yRadius),
488 Board::drawPolyline(
const std::vector<Point> & points,
491 int d = (depthValue != -1) ? depthValue : _nextDepth--;
492 std::vector<Point> v = points;
493 std::vector<Point>::iterator it = v.begin();
494 std::vector<Point>::iterator end = v.end();
495 while ( it != end ) {
496 (*it) = _state.unit( *it );
499 _shapes.push_back(
new Polyline( v,
false, _state.penColor, _state.fillColor,
508 Board::drawClosedPolyline(
const std::vector<Point> & points,
511 int d = (depthValue != -1) ? depthValue : _nextDepth--;
512 std::vector<Point> v = points;
513 std::vector<Point>::iterator it = v.begin();
514 std::vector<Point>::iterator end = v.end();
515 while ( it != end ) {
516 (*it) = _state.unit( *it );
519 _shapes.push_back(
new Polyline( v,
true, _state.penColor, _state.fillColor,
528 Board::fillPolyline(
const std::vector<Point> & points,
531 int d = (depthValue != -1) ? depthValue : _nextDepth--;
532 std::vector<Point> v = points;
533 std::vector<Point>::iterator it = v.begin();
534 std::vector<Point>::iterator end = v.end();
535 while ( it != end ) {
536 (*it) = _state.unit( *it );
548 Board::drawTriangle(
double x1,
double y1,
549 double x2,
double y2,
550 double x3,
double y3,
553 int d = (depthValue != -1) ? depthValue : _nextDepth--;
554 std::vector<Point> points;
555 points.push_back(
Point( _state.unit(x1), _state.unit(y1) ) );
556 points.push_back(
Point( _state.unit(x2), _state.unit(y2) ) );
557 points.push_back(
Point( _state.unit(x3), _state.unit(y3) ) );
558 _shapes.push_back(
new Polyline( points,
true, _state.penColor, _state.fillColor,
567 Board::drawTriangle(
const Point & p1,
572 int d = (depthValue != -1) ? depthValue : _nextDepth--;
573 std::vector<Point> points;
574 points.push_back(
Point( _state.unit(p1.
x), _state.unit(p1.
y) ) );
575 points.push_back(
Point( _state.unit(p2.
x), _state.unit(p2.
y) ) );
576 points.push_back(
Point( _state.unit(p3.
x), _state.unit(p3.
y) ) );
577 _shapes.push_back(
new Polyline( points,
true, _state.penColor, _state.fillColor,
586 Board::fillTriangle(
double x1,
double y1,
587 double x2,
double y2,
588 double x3,
double y3,
591 int d = (depthValue != -1) ? depthValue : _nextDepth--;
592 std::vector<Point> points;
593 points.push_back(
Point( _state.unit(x1), _state.unit(y1) ) );
594 points.push_back(
Point( _state.unit(x2), _state.unit(y2) ) );
595 points.push_back(
Point( _state.unit(x3), _state.unit(y3) ) );
605 Board::fillTriangle(
const Point & p1,
610 int d = (depthValue != -1) ? depthValue : _nextDepth--;
611 std::vector<Point> points;
612 points.push_back(
Point( _state.unit(p1.
x), _state.unit(p1.
y) ) );
613 points.push_back(
Point( _state.unit(p2.
x), _state.unit(p2.
y) ) );
614 points.push_back(
Point( _state.unit(p3.
x), _state.unit(p3.
y) ) );
624 Board::fillGouraudTriangle(
const Point & p1,
630 unsigned char divisions,
633 int d = (depthValue != -1) ? depthValue : _nextDepth--;
634 _shapes.push_back(
new GouraudTriangle(
Point( _state.unit(p1.
x), _state.unit(p1.
y) ), color1,
635 Point( _state.unit(p2.
x), _state.unit(p2.
y) ), color2,
636 Point( _state.unit(p3.
x), _state.unit(p3.
y) ), color3,
641 Board::fillGouraudTriangle(
const Point & p1,
642 const float brightness1,
644 const float brightness2,
646 const float brightness3,
647 unsigned char divisions,
653 color1.
red( static_cast<unsigned char>( std::min( 255.0f, color1.
red() * brightness1 ) ) );
654 color1.
green( static_cast<unsigned char>( std::min( 255.0f, color1.
green() * brightness1 ) ) );
655 color1.
blue( static_cast<unsigned char>( std::min( 255.0f, color1.
blue() * brightness1 ) ) );
656 color2.
red( static_cast<unsigned char>( std::min( 255.0f, color2.
red() * brightness2 ) ) );
657 color2.
green( static_cast<unsigned char>( std::min( 255.0f, color2.
green() * brightness2 ) ) );
658 color2.
blue( static_cast<unsigned char>( std::min( 255.0f, color2.
blue() * brightness2 ) ) );
659 color3.
red( static_cast<unsigned char>( std::min( 255.0f, color3.
red() * brightness3 ) ) );
660 color3.
green( static_cast<unsigned char>( std::min( 255.0f, color3.
green() * brightness3 ) ) );
661 color3.
blue( static_cast<unsigned char>( std::min( 255.0f, color3.
blue() * brightness3 ) ) );
662 fillGouraudTriangle(
Point( _state.unit(p1.
x), _state.unit(p1.
y) ), color1,
663 Point( _state.unit(p2.
x), _state.unit(p2.
y) ), color2,
664 Point( _state.unit(p3.
x), _state.unit(p3.
y) ), color3,
670 Board::drawText(
double x,
double y,
const char * text,
673 int d = (depthValue != -1) ? depthValue : _nextDepth--;
674 _shapes.push_back(
new Text( _state.unit(x), _state.unit(y), text,
675 _state.font, _state.fontSize, _state.penColor, d ) );
679 Board::drawText(
double x,
double y,
const std::string & str,
int depthValue )
681 int d = (depthValue != -1) ? depthValue : _nextDepth--;
682 _shapes.push_back(
new Text( _state.unit(x), _state.unit(y), str,
683 _state.font, _state.fontSize, _state.penColor, d ) );
687 Board::drawBoundingBox(
int depthValue )
689 int d = (depthValue != -1) ? depthValue : _nextDepth--;
690 Rect box = boundingBox();
691 _shapes.push_back(
new Rectangle( _state.unit(box.left),
692 _state.unit(box.top),
693 _state.unit(box.width),
694 _state.unit(box.height),
705 Board::setClippingRectangle(
double xLeft,
double yTop,
706 double rectWidth,
double rectHeight )
708 _clippingPath.clear();
709 _clippingPath << _state.unit(
Point( xLeft, yTop ) );
710 _clippingPath << _state.unit(
Point( xLeft + rectWidth, yTop ) );
711 _clippingPath << _state.unit(
Point( xLeft + rectWidth, yTop - rectHeight) );
712 _clippingPath << _state.unit(
Point( xLeft , yTop - rectHeight ) );
716 Board::setClippingPath(
const std::vector<Point> & points )
718 _clippingPath.clear();
719 std::vector<Point>::const_iterator it = points.begin();
720 std::vector<Point>::const_iterator end = points.end();
721 while ( it != end ) {
722 _clippingPath << _state.unit( *it );
728 Board::setClippingPath(
const Path & path )
730 _clippingPath = path;
731 _clippingPath.setClosed(
true );
732 if ( _clippingPath.size() > 1 ) {
733 if ( _clippingPath[0] == _clippingPath[ _clippingPath.size() - 1 ] )
734 _clippingPath.pop_back();
736 unsigned int n = _clippingPath.size();
737 for (
unsigned int i = 0; i < n; ++i ) {
738 _clippingPath[i] = _state.unit( _clippingPath[i] );
744 Board::addDuplicates(
const Shape & shape,
746 double dx,
double dy,
double scaleValue )
748 Shape * s = shape.clone();
751 if ( scaleValue != 1.0 )
752 s->scale( scaleValue );
753 s->translate( dx, dy );
759 Board::addDuplicates(
const Shape & shape,
761 double dx,
double dy,
762 double scaleX,
double scaleY,
765 Shape * s = shape.clone();
768 if ( scaleX != 1.0 || scaleY != 1.0 ) s->scale( scaleX, scaleY );
769 if ( dx != 0.0 || dy != 0.0 ) s->translate( dx, dy );
770 if ( angle != 0.0 ) s->rotate( angle );
776 Board::saveEPS( std::ostream &out, PageSize size,
double margin )
const
778 saveEPS( out, pageSizes[size][0], pageSizes[size][1], margin );
782 Board::saveEPS(
const char * filename, PageSize size,
double margin )
const
784 saveEPS( filename, pageSizes[size][0], pageSizes[size][1], margin );
789 Board::saveEPS(
const char * filename,
double pageWidth,
double pageHeight,
double margin )
const
791 std::ofstream file( filename );
792 saveEPS(file, pageWidth, pageHeight, margin);
797 Board::saveEPS( std::ostream &out,
double pageWidth,
double pageHeight,
double margin )
const
799 Rect box = boundingBox();
800 bool clipping = _clippingPath.size() > 2;
802 box = box && _clippingPath.boundingBox();
804 TransformEPS transform;
805 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
807 out <<
"%!PS-Adobe-2.0 EPSF-2.0" << std::endl;
808 out <<
"%%Title: output.eps " << std::endl;
809 out <<
"%%Creator: Board library (Copyleft)2007 Sebastien Fourey" << std::endl;
814 out <<
"%%CreationDate: " << str_time;
816 out <<
"%%BoundingBox: " << std::setprecision( 8 )
817 << transform.mapX( box.left ) <<
" "
818 << transform.mapY( box.top - box.height ) <<
" "
819 << transform.mapX( box.left + box.width ) <<
" "
820 << transform.mapY( box.top ) << std::endl;
822 out <<
"%Magnification: 1.0000" << std::endl;
823 out <<
"%%EndComments" << std::endl;
826 out <<
"/cp {closepath} bind def" << std::endl;
827 out <<
"/ef {eofill} bind def" << std::endl;
828 out <<
"/gr {grestore} bind def" << std::endl;
829 out <<
"/gs {gsave} bind def" << std::endl;
830 out <<
"/sa {save} bind def" << std::endl;
831 out <<
"/rs {restore} bind def" << std::endl;
832 out <<
"/l {lineto} bind def" << std::endl;
833 out <<
"/m {moveto} bind def" << std::endl;
834 out <<
"/rm {rmoveto} bind def" << std::endl;
835 out <<
"/n {newpath} bind def" << std::endl;
836 out <<
"/s {stroke} bind def" << std::endl;
837 out <<
"/sh {show} bind def" << std::endl;
838 out <<
"/slc {setlinecap} bind def" << std::endl;
839 out <<
"/slj {setlinejoin} bind def" << std::endl;
840 out <<
"/slw {setlinewidth} bind def" << std::endl;
841 out <<
"/srgb {setrgbcolor} bind def" << std::endl;
842 out <<
"/rot {rotate} bind def" << std::endl;
843 out <<
"/sc {scale} bind def" << std::endl;
844 out <<
"/sd {setdash} bind def" << std::endl;
845 out <<
"/ff {findfont} bind def" << std::endl;
846 out <<
"/sf {setfont} bind def" << std::endl;
847 out <<
"/scf {scalefont} bind def" << std::endl;
848 out <<
"/sw {stringwidth} bind def" << std::endl;
849 out <<
"/sd {setdash} bind def" << std::endl;
850 out <<
"/tr {translate} bind def" << std::endl;
851 out <<
" 0.5 setlinewidth" << std::endl;
855 _clippingPath.flushPostscript( out, transform );
856 out <<
" 0 slw clip " << std::endl;
862 r.flushPostscript( out, transform );
866 std::vector< Shape* > shapes = _shapes;
869 std::vector< Shape* >::const_iterator i = shapes.begin();
870 std::vector< Shape* >::const_iterator end = shapes.end();
873 (*i)->flushPostscript( out, transform );
876 out <<
"showpage" << std::endl;
877 out <<
"%%Trailer" << std::endl;
878 out <<
"%EOF" << std::endl;
884 Board::saveFIG(
const char * filename, PageSize size,
double margin,
bool includeFIGHeader )
const
886 saveFIG( filename, pageSizes[size][0], pageSizes[size][1], margin, includeFIGHeader );
889 Board::saveFIG( std::ostream &out, PageSize size,
double margin,
bool includeFIGHeader )
const
891 saveFIG( out, pageSizes[size][0], pageSizes[size][1], margin, includeFIGHeader );
894 Board::saveFIG(
const char * filename,
double pageWidth,
double pageHeight,
double margin,
895 bool includeFIGHeader )
const
897 std::ofstream file( filename );
898 saveFIG( file, pageWidth, pageHeight, margin, includeFIGHeader);
903 Board::saveFIG( std::ostream &file,
double pageWidth,
double pageHeight,
double margin,
bool includeFIGHeader )
const
907 TransformFIG transform;
908 Rect box = boundingBox();
909 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
910 transform.setDepthRange( *
this );
911 if(includeFIGHeader){
912 file <<
"#FIG 3.2 Produced by the Board library (Copyleft)2007 Sebastien Fourey\n";
913 file <<
"Portrait\n";
924 std::map<DGtal::Color,int> colormap;
938 std::vector< Shape* > shapes = _shapes;
940 std::vector< Shape* >::const_iterator i = shapes.begin();
941 std::vector< Shape* >::const_iterator end = shapes.end();
943 if ( colormap.find( (*i)->penColor() ) == colormap.end()
944 && (*i)->penColor().valid() )
945 colormap[ (*i)->penColor() ] = maxColor++;
946 if ( colormap.find( (*i)->fillColor() ) == colormap.end()
947 && (*i)->fillColor().valid() )
948 colormap[ (*i)->fillColor() ] = maxColor++;
952 if ( colormap.find( _backgroundColor ) == colormap.end()
953 && _backgroundColor.valid() )
954 colormap[ _backgroundColor ] = maxColor++;
957 std::map<DGtal::Color,int>::const_iterator iColormap = colormap.begin();
958 std::map<DGtal::Color,int>::const_iterator endColormap = colormap.end();
959 char colorString[255];
960 while ( iColormap != endColormap ) {
962 "0 %d #%02x%02x%02x\n",
964 iColormap->first.red(),
965 iColormap->first.green(),
966 iColormap->first.blue() );
967 if ( iColormap->second >= 32 ) file << colorString;
974 r.depth( std::numeric_limits<int>::max() );
975 r.flushFIG( file, transform, colormap );
982 (*i)->flushFIG( file, transform, colormap );
989 Board::saveSVG(
const char * filename, PageSize size,
double margin )
const
991 saveSVG( filename, pageSizes[size][0], pageSizes[size][1], margin );
995 Board::saveSVG( std::ostream &out, PageSize size,
double margin )
const
997 saveSVG( out, pageSizes[size][0], pageSizes[size][1], margin );
1002 Board::saveSVG(
const char * filename,
double pageWidth,
double pageHeight,
double margin )
const
1004 std::ofstream file( filename );
1005 saveSVG(file, pageWidth, pageHeight, margin);
1012 Board::saveSVG( std::ostream &file,
double pageWidth,
double pageHeight,
double margin,
string filename )
const
1015 TransformSVG transform;
1016 Rect box = boundingBox();
1017 bool clipping = _clippingPath.size() > 2;
1019 box = box && _clippingPath.boundingBox();
1020 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
1022 file <<
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" << std::endl;
1023 file <<
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"" << std::endl;
1024 file <<
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" << std::endl;
1026 if ( pageWidth > 0 && pageHeight > 0 ) {
1027 file <<
"<svg width=\""
1028 << pageWidth <<
"mm\" height=\""
1029 << pageHeight <<
"mm\" " << std::endl;
1030 file <<
" viewBox=\"0 0 "
1031 << pageWidth * ppmm <<
" "
1032 << pageHeight * ppmm <<
"\" " << std::endl;
1033 file <<
" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" >" << std::endl;
1035 file <<
"<svg width=\""
1036 << ( box.width / ppmm ) <<
"mm"
1038 << ( box.height / ppmm ) <<
"mm"
1039 <<
"\" " << std::endl;
1040 file <<
" viewBox=\"0 0 "
1042 << box.height <<
"\" " << std::endl;
1043 file <<
" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" >" << std::endl;
1047 file <<
"<desc>" << filename
1048 <<
", created with the Board library (Copyleft) 2007 Sebastien Fourey"
1049 <<
"</desc>" << std::endl;
1052 file <<
"<g clip-rule=\"nonzero\">\n"
1053 <<
" <clipPath id=\"GlobalClipPath\">\n"
1054 <<
" <path clip-rule=\"evenodd\" d=\"";
1055 _clippingPath.flushSVGCommands( file, transform );
1057 file <<
" </clipPath>\n";
1058 file <<
"<g clip-path=\"url(#GlobalClipPath)\">\n";
1064 r.flushSVG( file, transform );
1068 std::vector< Shape* > shapes = _shapes;
1070 std::vector< Shape* >::const_iterator i = shapes.begin();
1071 std::vector< Shape* >::const_iterator end = shapes.end();
1072 while ( i != end ) {
1073 (*i)->flushSVG( file, transform );
1078 file <<
"</g>\n</g>";
1079 file <<
"</svg>" << std::endl;
1085 Board::save(
const char * filename,
double pageWidth,
double pageHeight,
double margin )
const
1087 const char * extension = filename + strlen( filename );
1088 while ( extension > filename && *extension !=
'.' )
1090 if ( !(strcmp( extension,
".eps" )) || !(strcmp( extension,
".EPS" )) ) {
1091 saveEPS( filename, pageWidth, pageHeight, margin );
1094 if ( !(strcmp( extension,
".fig" )) || !(strcmp( extension,
".FIG" )) ) {
1095 saveFIG( filename, pageWidth, pageHeight, margin );
1098 if ( !(strcmp( extension,
".svg" )) || !(strcmp( extension,
".SVG" )) ) {
1099 saveSVG( filename, pageWidth, pageHeight, margin );
1102 if ( !(strcmp( extension,
".tikz" )) || !(strcmp( extension,
".TIKZ" )) ) {
1103 saveTikZ( filename, pageWidth, pageHeight, margin );
1109 Board::save(
const char * filename, PageSize size,
double margin )
const
1111 save( filename, pageSizes[size][0], pageSizes[size][1], margin );
1116 Board::saveCairo(
const char * filename, CairoType type, PageSize size,
double margin )
const
1118 saveCairo( filename, type, pageSizes[size][0], pageSizes[size][1], margin );
1121 Board::saveCairo(
const char * filename, CairoType type,
double pageWidth,
double pageHeight,
double margin )
const
1123 cairo_surface_t *surface;
1126 double cairoWidth, cairoHeight;
1128 TransformCairo transform;
1129 Rect box = boundingBox();
1131 bool clipping = _clippingPath.size() > 2;
1133 box = box && _clippingPath.boundingBox();
1134 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
1136 if ( pageWidth > 0 && pageHeight > 0 )
1138 cairoWidth = pageWidth;
1139 cairoHeight = pageHeight;
1143 cairoWidth = box.width;
1144 cairoHeight = box.height;
1150 surface = cairo_pdf_surface_create (filename, cairoWidth, cairoHeight);
break;
1152 surface = cairo_ps_surface_create (filename, cairoWidth, cairoHeight);
break;
1154 surface = cairo_ps_surface_create (filename, cairoWidth, cairoHeight);
1155 cairo_ps_surface_set_eps(surface,
true);
break;
1157 surface = cairo_svg_surface_create (filename, cairoWidth, cairoHeight);
break;
1160 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, (
int)cairoWidth, (
int)cairoHeight);
1163 cr = cairo_create (surface);
1174 r.flushCairo( cr, transform );
1178 std::vector< Shape* > shapes = _shapes;
1180 std::vector< Shape* >::const_iterator i = shapes.begin();
1181 std::vector< Shape* >::const_iterator end = shapes.end();
1182 while ( i != end ) {
1183 (*i)->flushCairo( cr, transform );
1188 cairo_surface_write_to_png (surface, filename);
1191 cairo_surface_destroy (surface);
1196 Board::saveTikZ(
const char * filename, PageSize size,
double margin )
const
1198 saveTikZ( filename, pageSizes[size][0], pageSizes[size][1], margin );
1202 Board::saveTikZ( std::ostream & out, PageSize size,
double margin )
const
1204 saveTikZ( out, pageSizes[size][0], pageSizes[size][1], margin );
1208 Board::saveTikZ(
const char * filename,
double pageWidth,
double pageHeight,
double margin )
const
1210 std::ofstream file( filename );
1211 saveTikZ(file, pageHeight, pageHeight, margin);
1216 Board::saveTikZ( std::ostream &out,
double pageWidth,
double pageHeight,
double margin )
const
1218 TransformTikZ transform;
1219 Rect box = boundingBox();
1220 bool clipping = _clippingPath.size() > 2;
1222 box = box && _clippingPath.boundingBox();
1223 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
1225 out <<
"\\begin{tikzpicture}[anchor=south west,text depth=0,x={(1pt,0pt)},y={(0pt,-1pt)}]" << std::endl;
1255 _clippingPath.flushSVGCommands( out, transform );
1261 Rectangle r( box,
Color::None, _backgroundColor, 0.0 );
1262 r.flushTikZ( out, transform );
1266 std::vector< Shape* > shapes = _shapes;
1268 std::vector< Shape* >::const_iterator i = shapes.begin();
1269 std::vector< Shape* >::const_iterator end = shapes.end();
1270 while ( i != end ) {
1271 (*i)->flushTikZ( out, transform );
1277 out <<
"\\end{tikzpicture}" << std::endl;