DGtal 1.3.0
Loading...
Searching...
No Matches
Board.cpp
1/* -*- mode: c++ -*- */
10/*
11 * \@copyright This File is part of the Board library which is
12 * licensed under the terms of the GNU Lesser General Public Licence.
13 * See the LICENCE file for further details.
14 */
15
16
17#include "Board.h"
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"
23#include <fstream>
24#include <iostream>
25#include <iomanip>
26#include <typeinfo>
27#include <ctime>
28#include <cstring>
29#include <map>
30#include <algorithm>
31#include <cstdio>
32
33#ifdef WITH_CAIRO
34// cairo
35#if defined(__clang__)
36#pragma clang diagnostic push
37#pragma clang diagnostic ignored "-Wdocumentation"
38#endif
39#include <cairo.h>
40#include <cairo-pdf.h>
41#include <cairo-ps.h>
42#include <cairo-svg.h>
43#if defined(__clang__)
44#pragma clang diagnostic pop
45#endif
46// cairo
47#endif
48
49
50#if defined( WIN32 )
51#define _USE_MATH_DEFINES
52#include <math.h>
53#else
54#include <cmath>
55#endif //win32
56
57#ifdef _MSC_VER
58//#define NOMINMAX
59//#include <windows.h>
60//#ifdef M_PI
61//#undef M_PI
62//#endif
63//C++ exception specification ignored except
64//to indicate a function is not __declspec(nothrow)
65#pragma warning(disable : 4290)
66#endif
67
68#ifdef _MSC_VER
69#if defined( max )
70#undef max
71#define _HAS_MSVC_MAX_ true
72#endif
73#if defined( min )
74#undef min
75#define _HAS_MSVC_MIN_ true
76#endif
77#endif
78
79
80namespace {
81 const float pageSizes[3][2] = { { 0.0f, 0.0f }, // BoundingBox
82 { 210.0f, 297.0f },
83 { 8.5f*25.4f, 11.0f*25.4f } };
84 const float ppmm = 720.0f / 254.0f;
85}
86
87namespace LibBoard {
88
89const double Board::Degree = 3.14159265358979323846 / 180.0;
90
92{
95 lineWidth = 0.5;
96 lineStyle = Shape::SolidStyle;
97 lineCap = Shape::ButtCap;
98 lineJoin = Shape::MiterJoin;
100 fontSize = 11.0;
101 unitFactor = 1.0;
102}
103
104Board::Board( const DGtal::Color & bgColor )
105 : _backgroundColor( bgColor )
106{
107}
108
109Board::Board( const Board & other )
110 : ShapeList( other ),
111 _state( other._state ),
112 _backgroundColor( other._backgroundColor )
113{
114}
115
116Board &
117Board::operator=( const Board & other )
118{
119 free();
120 if ( ! other._shapes.size() ) return (*this);
121 _shapes.resize( other._shapes.size(), 0 );
122 std::vector<Shape*>::iterator t = _shapes.begin();
123 std::vector<Shape*>::const_iterator i = other._shapes.begin();
124 std::vector<Shape*>::const_iterator end = other._shapes.end();
125 while ( i != end ) {
126 *t = (*i)->clone();
127 ++i; ++t;
128 }
129 return *this;
130}
131
133Board::operator<<( const Shape & shape )
134{
136 return *this;
137}
138
141{
142 setUnit( unit );
143 return *this;
144}
145
147{
148
149}
150
151void
153{
155 _backgroundColor = color;
156}
157
158
159Shape &
160Board::rotate( double angle, const Point & aCenter )
161{
162 ShapeList::rotate( angle, aCenter );
163 _clippingPath.rotate( angle, aCenter );
164 return (*this);
165}
166
167Shape &
168Board::rotate( double angle )
169{
170 ShapeList::rotate( angle );
171 _clippingPath.rotate( angle, center() );
172 return (*this);
173}
174
175Shape &
176Board::translate( double dx, double dy )
177{
178 ShapeList::translate( dx, dy );
179 _clippingPath.translate( dx, dy );
180 return (*this);
181}
182
183Shape &
184Board::scale( double sx, double sy )
185{
186 Point delta = _clippingPath.center() - center();
187 delta.x *= sx;
188 delta.y *= sy;
189 _clippingPath.scale( sx, sy );
190 ShapeList::scale( sx, sy );
191 delta = ( center() + delta ) - _clippingPath.center();
192 _clippingPath.translate( delta.x, delta.y );
193 return (*this);
194}
195
196Shape &
197Board::scale( double s )
198{
199 Point delta = _clippingPath.center() - center();
200 delta *= s;
201 _clippingPath.scale( s );
202 ShapeList::scale( s );
203 delta = ( center() + delta ) - _clippingPath.center();
204 _clippingPath.translate( delta.x, delta.y );
205 return (*this);
206}
207
208Board
209Board::rotated( double angle, const Point & aCenter )
210{
211 return static_cast<const Board &>( Board( *this ).rotate( angle, aCenter ) );
212}
213
214Board
215Board::rotated( double angle )
216{
217 return static_cast<const Board &>( Board( *this ).rotate( angle ) );
218}
219
220Board
221Board::translated( double dx, double dy )
222{
223 return static_cast<const Board &>( Board( *this ).translate( dx, dy ) );
224}
225
226Board
227Board::scaled( double sx, double sy )
228{
229 return static_cast<const Board &>( Board( *this ).scale( sx, sy ) );
230}
231
232Board
233Board::scaled( double s )
234{
235 return static_cast<const Board &>( Board( *this ).scale( s ) );
236}
237
238
239void
241{
242 switch ( unit ) {
243 case UPoint:
244 _state.unitFactor = 1.0;
245 break;
246 case UInche:
247 _state.unitFactor = 25.4f * ppmm;
248 break;
249 case UCentimeter:
250 _state.unitFactor = 10.0f * ppmm;
251 break;
252 case UMillimeter:
253 _state.unitFactor = ppmm;
254 break;
255 }
256}
257
258void
259Board::setUnit( double factor, Unit unit )
260{
261 switch ( unit ) {
262 case UPoint:
263 _state.unitFactor = factor;
264 break;
265 case UInche:
266 _state.unitFactor = 720.0f * factor;
267 break;
268 case UCentimeter:
269 _state.unitFactor = 10.0f * ppmm * factor;
270 break;
271 case UMillimeter:
272 _state.unitFactor = ppmm * factor;
273 break;
274 }
275}
276
277Board &
278Board::setPenColorRGBi( unsigned char red,
279 unsigned char green,
280 unsigned char blue,
281 unsigned char alpha )
282{
283 _state.penColor.setRGBi( red, green, blue, alpha );
284 return *this;
285}
286
287Board &
289 float green,
290 float blue,
291 float alpha )
292{
293 _state.penColor.setRGBf( red, green, blue, alpha );
294 return *this;
295}
296
297Board &
299{
300 _state.penColor = color;
301 return *this;
302}
303
304Board &
305Board::setFillColorRGBi( unsigned char red,
306 unsigned char green,
307 unsigned char blue,
308 unsigned char alpha )
309{
310 _state.fillColor.setRGBi( red, green, blue, alpha );
311 return *this;
312}
313
314Board &
315Board::setFillColorRGBf( float red, float green, float blue, float alpha )
316{
317 _state.fillColor.setRGBf( red, green, blue, alpha );
318 return *this;
319}
320
321Board &
323{
324 _state.fillColor = color;
325 return *this;
326}
327
328Board &
329Board::setLineWidth( double width )
330{
331 _state.lineWidth = width;
332 return *this;
333}
334
335Board &
336Board::setFont( const Fonts::Font font, double fontSize )
337{
338 _state.font = font;
339 _state.fontSize = fontSize;
340 return *this;
341}
342
343Board &
344Board::setFontSize( double fontSize )
345{
346 _state.fontSize = fontSize;
347 return *this;
348}
349
350void
352{
353 _backgroundColor = color;
354}
355
356void
357Board::drawDot( double x, double y, int depthValue )
358{
359 if ( depthValue != -1 )
360 _shapes.push_back( new Dot( _state.unit(x), _state.unit(y),
361 _state.penColor, _state.lineWidth, depthValue ) );
362 else
363 _shapes.push_back( new Dot( _state.unit(x), _state.unit(y),
365}
366
367void
368Board::drawLine( double x1, double y1, double x2, double y2,
369 int depthValue /* = -1 */ )
370{
371 if ( depthValue != -1 )
372 _shapes.push_back( new Line( _state.unit(x1), _state.unit(y1),
373 _state.unit(x2), _state.unit(y2),
375 _state.lineStyle, _state.lineCap, _state.lineJoin, depthValue ) );
376 else
377 _shapes.push_back( new Line( _state.unit(x1), _state.unit(y1),
378 _state.unit(x2), _state.unit(y2),
381}
382
383void
384Board::drawQuadraticBezierCurve( double x1, double y1, double x2, double y2, double x3, double y3,
385 int depthValue /* = -1 */ )
386{
387 if ( depthValue != -1 )
388 _shapes.push_back( new QuadraticBezierCurve( _state.unit(x1), _state.unit(y1),
389 _state.unit(x2), _state.unit(y2), _state.unit(x3), _state.unit(y3),
391 _state.lineStyle, _state.lineCap, _state.lineJoin, depthValue ) );
392 else
393 _shapes.push_back( new QuadraticBezierCurve( _state.unit(x1), _state.unit(y1),
394 _state.unit(x2), _state.unit(y2), _state.unit(x3), _state.unit(y3),
397}
398
399void
400Board::drawArrow( double x1, double y1, double x2, double y2,
401 bool filledArrow /* = false */,
402 int depthValue /* = -1 */ )
403{
404 if ( depthValue != -1 )
405 _shapes.push_back( new Arrow( _state.unit(x1), _state.unit(y1),
406 _state.unit(x2), _state.unit(y2),
409 else
410 _shapes.push_back( new Arrow( _state.unit(x1), _state.unit(y1),
411 _state.unit(x2), _state.unit(y2),
414}
415
416void
417Board::drawRectangle( double x, double y,
418 double width, double height,
419 int depthValue /* = -1 */ )
420{
421 int d = (depthValue != -1) ? depthValue : _nextDepth--;
422 _shapes.push_back( new Rectangle( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height),
425}
426
427void
428Board::drawImage(std::string filename, double x, double y,
429 double width, double height,
430 int depthValue, double alpha /* = -1 */ )
431{
432 int d = (depthValue != -1) ? depthValue : _nextDepth--;
433 _shapes.push_back( new Image( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height),
434 filename, d, alpha ) );
435}
436
437
438void
439Board::fillRectangle( double x, double y,
440 double width, double height,
441 int depthValue /* = -1 */ )
442{
443 int d = (depthValue != -1) ? depthValue : _nextDepth--;
444 _shapes.push_back( new Rectangle( _state.unit(x), _state.unit(y), _state.unit(width), _state.unit(height),
447 d ) );
448}
449
450void
451Board::drawCircle( double x, double y, double radius,
452 int depthValue /* = -1 */ )
453{
454 int d = (depthValue != -1) ? depthValue : _nextDepth--;
455 _shapes.push_back( new Circle( _state.unit(x), _state.unit(y), _state.unit(radius),
458}
459
460void
461Board::drawArc(double x, double y, double radius, double angle1, double angle2,
462 bool neg, int depthValue /*= -1*/ ){
463 int d = (depthValue != -1) ? depthValue : _nextDepth--;
464 _shapes.push_back( new Arc( _state.unit(x), _state.unit(y), _state.unit(radius),
465 angle1, angle2, neg,_state.penColor,
467}
468
469
470void
471Board::fillCircle( double x, double y,
472 double radius,
473 int depthValue /* = -1 */ )
474{
475 int d = (depthValue != -1) ? depthValue : _nextDepth--;
476 _shapes.push_back( new Circle( _state.unit(x), _state.unit(y), _state.unit(radius),
478 0.0f, _state.lineStyle, d ) );
479}
480
481void
482Board::drawEllipse( double x, double y,
483 double xRadius, double yRadius,
484 int depthValue /* = -1 */ )
485{
486 int d = (depthValue != -1) ? depthValue : _nextDepth--;
487 _shapes.push_back( new Ellipse( _state.unit(x), _state.unit(y),
488 _state.unit(xRadius), _state.unit(yRadius),
493 d ) );
494}
495
496void
497Board::fillEllipse( double x, double y,
498 double xRadius, double yRadius,
499 int depthValue /* = -1 */ )
500{
501 int d = depthValue ? depthValue : _nextDepth--;
502 _shapes.push_back( new Ellipse( _state.unit(x), _state.unit(y), _state.unit(xRadius), _state.unit(yRadius),
505 0.0f,
507 d ) );
508}
509
510void
511Board::drawPolyline( const std::vector<Point> & points,
512 int depthValue /* = -1 */ )
513{
514 int d = (depthValue != -1) ? depthValue : _nextDepth--;
515 std::vector<Point> v = points;
516 std::vector<Point>::iterator it = v.begin();
517 std::vector<Point>::iterator end = v.end();
518 while ( it != end ) {
519 (*it) = _state.unit( *it );
520 ++it;
521 }
522 _shapes.push_back( new Polyline( v, false, _state.penColor, _state.fillColor,
527 d ) );
528}
529
530void
531Board::drawClosedPolyline( const std::vector<Point> & points,
532 int depthValue /* = -1 */ )
533{
534 int d = (depthValue != -1) ? depthValue : _nextDepth--;
535 std::vector<Point> v = points;
536 std::vector<Point>::iterator it = v.begin();
537 std::vector<Point>::iterator end = v.end();
538 while ( it != end ) {
539 (*it) = _state.unit( *it );
540 ++it;
541 }
542 _shapes.push_back( new Polyline( v, true, _state.penColor, _state.fillColor,
547 d ) );
548}
549
550void
551Board::fillPolyline( const std::vector<Point> & points,
552 int depthValue /* = -1 */ )
553{
554 int d = (depthValue != -1) ? depthValue : _nextDepth--;
555 std::vector<Point> v = points;
556 std::vector<Point>::iterator it = v.begin();
557 std::vector<Point>::iterator end = v.end();
558 while ( it != end ) {
559 (*it) = _state.unit( *it );
560 ++it;
561 }
562 _shapes.push_back( new Polyline( v, true, DGtal::Color::None, _state.penColor,
563 0.0f,
567 d ) );
568}
569
570void
571Board::drawTriangle( double x1, double y1,
572 double x2, double y2,
573 double x3, double y3,
574 int depthValue /* = -1 */ )
575{
576 int d = (depthValue != -1) ? depthValue : _nextDepth--;
577 std::vector<Point> points;
578 points.push_back( Point( _state.unit(x1), _state.unit(y1) ) );
579 points.push_back( Point( _state.unit(x2), _state.unit(y2) ) );
580 points.push_back( Point( _state.unit(x3), _state.unit(y3) ) );
581 _shapes.push_back( new Polyline( points, true, _state.penColor, _state.fillColor,
586 d ) );
587}
588
589void
591 const Point & p2,
592 const Point & p3,
593 int depthValue /* = -1 */ )
594{
595 int d = (depthValue != -1) ? depthValue : _nextDepth--;
596 std::vector<Point> points;
597 points.push_back( Point( _state.unit(p1.x), _state.unit(p1.y) ) );
598 points.push_back( Point( _state.unit(p2.x), _state.unit(p2.y) ) );
599 points.push_back( Point( _state.unit(p3.x), _state.unit(p3.y) ) );
600 _shapes.push_back( new Polyline( points, true, _state.penColor, _state.fillColor,
605 d ) );
606}
607
608void
609Board::fillTriangle( double x1, double y1,
610 double x2, double y2,
611 double x3, double y3,
612 int depthValue /* = -1 */ )
613{
614 int d = (depthValue != -1) ? depthValue : _nextDepth--;
615 std::vector<Point> points;
616 points.push_back( Point( _state.unit(x1), _state.unit(y1) ) );
617 points.push_back( Point( _state.unit(x2), _state.unit(y2) ) );
618 points.push_back( Point( _state.unit(x3), _state.unit(y3) ) );
619 _shapes.push_back( new Polyline( points, true, DGtal::Color::None, _state.penColor,
620 0.0f,
624 d ) );
625}
626
627void
629 const Point & p2,
630 const Point & p3,
631 int depthValue /* = -1 */ )
632{
633 int d = (depthValue != -1) ? depthValue : _nextDepth--;
634 std::vector<Point> points;
635 points.push_back( Point( _state.unit(p1.x), _state.unit(p1.y) ) );
636 points.push_back( Point( _state.unit(p2.x), _state.unit(p2.y) ) );
637 points.push_back( Point( _state.unit(p3.x), _state.unit(p3.y) ) );
638 _shapes.push_back( new Polyline( points, true, DGtal::Color::None, _state.penColor,
639 0.0f,
643 d ) );
644}
645
646void
648 const DGtal::Color & color1,
649 const Point & p2,
650 const DGtal::Color & color2,
651 const Point & p3,
652 const DGtal::Color & color3,
653 unsigned char divisions,
654 int depthValue /* = -1 */ )
655{
656 int d = (depthValue != -1) ? depthValue : _nextDepth--;
657 _shapes.push_back( new GouraudTriangle( Point( _state.unit(p1.x), _state.unit(p1.y) ), color1,
658 Point( _state.unit(p2.x), _state.unit(p2.y) ), color2,
659 Point( _state.unit(p3.x), _state.unit(p3.y) ), color3,
660 divisions, d ) );
661}
662
663void
665 const float brightness1,
666 const Point & p2,
667 const float brightness2,
668 const Point & p3,
669 const float brightness3,
670 unsigned char divisions,
671 int depthValue /* = -1 */ )
672{
673 DGtal::Color color1( _state.penColor );
674 DGtal::Color color2( _state.penColor );
675 DGtal::Color color3( _state.penColor );
676 color1.red( static_cast<unsigned char>( std::min( 255.0f, color1.red() * brightness1 ) ) );
677 color1.green( static_cast<unsigned char>( std::min( 255.0f, color1.green() * brightness1 ) ) );
678 color1.blue( static_cast<unsigned char>( std::min( 255.0f, color1.blue() * brightness1 ) ) );
679 color2.red( static_cast<unsigned char>( std::min( 255.0f, color2.red() * brightness2 ) ) );
680 color2.green( static_cast<unsigned char>( std::min( 255.0f, color2.green() * brightness2 ) ) );
681 color2.blue( static_cast<unsigned char>( std::min( 255.0f, color2.blue() * brightness2 ) ) );
682 color3.red( static_cast<unsigned char>( std::min( 255.0f, color3.red() * brightness3 ) ) );
683 color3.green( static_cast<unsigned char>( std::min( 255.0f, color3.green() * brightness3 ) ) );
684 color3.blue( static_cast<unsigned char>( std::min( 255.0f, color3.blue() * brightness3 ) ) );
685 fillGouraudTriangle( Point( _state.unit(p1.x), _state.unit(p1.y) ), color1,
686 Point( _state.unit(p2.x), _state.unit(p2.y) ), color2,
687 Point( _state.unit(p3.x), _state.unit(p3.y) ), color3,
688 divisions,
689 depthValue );
690}
691
692void
693Board::drawText( double x, double y, const char * text,
694 int depthValue /* = -1 */ )
695{
696 int d = (depthValue != -1) ? depthValue : _nextDepth--;
697 _shapes.push_back( new Text( _state.unit(x), _state.unit(y), text,
699}
700
701void
702Board::drawText( double x, double y, const std::string & str, int depthValue /* = -1 */ )
703{
704 int d = (depthValue != -1) ? depthValue : _nextDepth--;
705 _shapes.push_back( new Text( _state.unit(x), _state.unit(y), str,
707}
708
709void
710Board::drawBoundingBox( int depthValue /* = -1 */ )
711{
712 int d = (depthValue != -1) ? depthValue : _nextDepth--;
713 Rect box = boundingBox();
714 _shapes.push_back( new Rectangle( _state.unit(box.left),
715 _state.unit(box.top),
716 _state.unit(box.width),
717 _state.unit(box.height),
724 d ) );
725}
726
727void
728Board::setClippingRectangle( double xLeft, double yTop,
729 double rectWidth, double rectHeight )
730{
732 _clippingPath << _state.unit( Point( xLeft, yTop ) );
733 _clippingPath << _state.unit( Point( xLeft + rectWidth, yTop ) );
734 _clippingPath << _state.unit( Point( xLeft + rectWidth, yTop - rectHeight) );
735 _clippingPath << _state.unit( Point( xLeft , yTop - rectHeight ) );
736}
737
738void
739Board::setClippingPath( const std::vector<Point> & points )
740{
742 std::vector<Point>::const_iterator it = points.begin();
743 std::vector<Point>::const_iterator end = points.end();
744 while ( it != end ) {
745 _clippingPath << _state.unit( *it );
746 ++it;
747 }
748}
749
750void
752{
753 _clippingPath = path;
754 _clippingPath.setClosed( true );
755 if ( _clippingPath.size() > 1 ) {
756 if ( _clippingPath[0] == _clippingPath[ _clippingPath.size() - 1 ] )
758 }
759 unsigned int n = _clippingPath.size();
760 for ( unsigned int i = 0; i < n; ++i ) {
762 }
763}
764
765
766void
768 unsigned int times,
769 double dx, double dy, double scaleValue )
770{
771 Shape * s = shape.clone();
772 while ( times-- ) {
773 (*this) << (*s);
774 if ( scaleValue != 1.0 )
775 s->scale( scaleValue );
776 s->translate( dx, dy );
777 }
778 delete s;
779}
780
781void
783 unsigned int times,
784 double dx, double dy,
785 double scaleX, double scaleY,
786 double angle )
787{
788 Shape * s = shape.clone();
789 while ( times-- ) {
790 (*this) << (*s);
791 if ( scaleX != 1.0 || scaleY != 1.0 ) s->scale( scaleX, scaleY );
792 if ( dx != 0.0 || dy != 0.0 ) s->translate( dx, dy );
793 if ( angle != 0.0 ) s->rotate( angle );
794 }
795 delete s;
796}
797
798void
799Board::saveEPS( std::ostream &out, PageSize size, double margin ) const
800{
801 saveEPS( out, pageSizes[size][0], pageSizes[size][1], margin );
802}
803
804void
805Board::saveEPS( const char * filename, PageSize size, double margin ) const
806{
807 saveEPS( filename, pageSizes[size][0], pageSizes[size][1], margin );
808}
809
810
811void
812Board::saveEPS( const char * filename, double pageWidth, double pageHeight, double margin ) const
813{
814 std::ofstream file( filename );
815 saveEPS(file, pageWidth, pageHeight, margin);
816 file.close();
817}
818
819void
820Board::saveEPS( std::ostream &out, double pageWidth, double pageHeight, double margin ) const
821{
822 Rect box = boundingBox();
823 bool clipping = _clippingPath.size() > 2;
824 if ( clipping )
825 box = box && _clippingPath.boundingBox();
826
827 TransformEPS transform;
828 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
829
830 out << "%!PS-Adobe-2.0 EPSF-2.0" << std::endl;
831 out << "%%Title: output.eps " << std::endl;
832 out << "%%Creator: Board library (Copyleft)2007 Sebastien Fourey" << std::endl;
833 {
834 time_t t = time(0);
835 char str_time[255];
836 secured_ctime( str_time, &t, 255 );
837 out << "%%CreationDate: " << str_time;
838 }
839 out << "%%BoundingBox: " << std::setprecision( 8 )
840 << transform.mapX( box.left ) << " "
841 << transform.mapY( box.top - box.height ) << " "
842 << transform.mapX( box.left + box.width ) << " "
843 << transform.mapY( box.top ) << std::endl;
844
845 out << "%Magnification: 1.0000" << std::endl;
846 out << "%%EndComments" << std::endl;
847
848 out << std::endl;
849 out << "/cp {closepath} bind def" << std::endl;
850 out << "/ef {eofill} bind def" << std::endl;
851 out << "/gr {grestore} bind def" << std::endl;
852 out << "/gs {gsave} bind def" << std::endl;
853 out << "/sa {save} bind def" << std::endl;
854 out << "/rs {restore} bind def" << std::endl;
855 out << "/l {lineto} bind def" << std::endl;
856 out << "/m {moveto} bind def" << std::endl;
857 out << "/rm {rmoveto} bind def" << std::endl;
858 out << "/n {newpath} bind def" << std::endl;
859 out << "/s {stroke} bind def" << std::endl;
860 out << "/sh {show} bind def" << std::endl;
861 out << "/slc {setlinecap} bind def" << std::endl;
862 out << "/slj {setlinejoin} bind def" << std::endl;
863 out << "/slw {setlinewidth} bind def" << std::endl;
864 out << "/srgb {setrgbcolor} bind def" << std::endl;
865 out << "/rot {rotate} bind def" << std::endl;
866 out << "/sc {scale} bind def" << std::endl;
867 out << "/sd {setdash} bind def" << std::endl;
868 out << "/ff {findfont} bind def" << std::endl;
869 out << "/sf {setfont} bind def" << std::endl;
870 out << "/scf {scalefont} bind def" << std::endl;
871 out << "/sw {stringwidth} bind def" << std::endl;
872 out << "/sd {setdash} bind def" << std::endl;
873 out << "/tr {translate} bind def" << std::endl;
874 out << " 0.5 setlinewidth" << std::endl;
875
876 if ( clipping ) {
877 out << " newpath ";
878 _clippingPath.flushPostscript( out, transform );
879 out << " 0 slw clip " << std::endl;
880 }
881
882 // Draw the background color if needed.
885 r.flushPostscript( out, transform );
886 }
887
888 // Draw the shapes
889 std::vector< Shape* > shapes = _shapes;
890
891 stable_sort( shapes.begin(), shapes.end(), shapeGreaterDepth );
892 std::vector< Shape* >::const_iterator i = shapes.begin();
893 std::vector< Shape* >::const_iterator end = shapes.end();
894
895 while ( i != end ) {
896 (*i)->flushPostscript( out, transform );
897 ++i;
898 }
899 out << "showpage" << std::endl;
900 out << "%%Trailer" << std::endl;
901 out << "%EOF" << std::endl;
902}
903
904
905
906void
907Board::saveFIG( const char * filename, PageSize size, double margin, bool includeFIGHeader ) const
908{
909 saveFIG( filename, pageSizes[size][0], pageSizes[size][1], margin, includeFIGHeader );
910}
911void
912Board::saveFIG( std::ostream &out, PageSize size, double margin, bool includeFIGHeader ) const
913{
914 saveFIG( out, pageSizes[size][0], pageSizes[size][1], margin, includeFIGHeader );
915}
916void
917Board::saveFIG( const char * filename, double pageWidth, double pageHeight, double margin,
918 bool includeFIGHeader ) const
919{
920 std::ofstream file( filename );
921 saveFIG( file, pageWidth, pageHeight, margin, includeFIGHeader);
922 file.close();
923}
924
925void
926Board::saveFIG( std::ostream &file, double pageWidth, double pageHeight, double margin, bool includeFIGHeader ) const
927{
928
929
930 TransformFIG transform;
931 Rect box = boundingBox();
932 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
933 transform.setDepthRange( *this );
934 if(includeFIGHeader){
935 file << "#FIG 3.2 Produced by the Board library (Copyleft)2007 Sebastien Fourey\n";
936 file << "Portrait\n";
937 file << "Center\n";
938 file << "Metric\n";
939 file << "A4\n";
940 file << "100.00\n";
941 file << "Single\n";
942 file << "-2\n";
943 file << "1200 2\n";
944 }else{
945 file << "\n";
946 }
947 std::map<DGtal::Color,int> colormap;
948 int maxColor = 32;
949
950
951 colormap[DGtal::Color(0,0,0)] = 0;
952 colormap[DGtal::Color(0,0,255)] = 1;
953 colormap[DGtal::Color(0,255,0)] = 2;
954 colormap[DGtal::Color(0,255,255)] = 0;
955 colormap[DGtal::Color(255,0,0)] = 4;
956 colormap[DGtal::Color(255,0,255)] = 0;
957 colormap[DGtal::Color(255,255,0)] = 6;
958 colormap[DGtal::Color(255,255,255)] = 7;
959
960
961 std::vector< Shape* > shapes = _shapes;
962 stable_sort( shapes.begin(), shapes.end(), shapeGreaterDepth );
963 std::vector< Shape* >::const_iterator i = shapes.begin();
964 std::vector< Shape* >::const_iterator end = shapes.end();
965 while ( i != end ) {
966 if ( colormap.find( (*i)->penColor() ) == colormap.end()
967 && (*i)->penColor().valid() )
968 colormap[ (*i)->penColor() ] = maxColor++;
969 if ( colormap.find( (*i)->fillColor() ) == colormap.end()
970 && (*i)->fillColor().valid() )
971 colormap[ (*i)->fillColor() ] = maxColor++;
972 ++i;
973 }
974
975 if ( colormap.find( _backgroundColor ) == colormap.end()
977 colormap[ _backgroundColor ] = maxColor++;
978
979 // Write the colormap
980 std::map<DGtal::Color,int>::const_iterator iColormap = colormap.begin();
981 std::map<DGtal::Color,int>::const_iterator endColormap = colormap.end();
982 char colorString[255];
983 while ( iColormap != endColormap ) {
984 secured_sprintf( colorString, 255,
985 "0 %d #%02x%02x%02x\n",
986 iColormap->second,
987 iColormap->first.red(),
988 iColormap->first.green(),
989 iColormap->first.blue() );
990 if ( iColormap->second >= 32 ) file << colorString;
991 ++iColormap;
992 }
993
994 // Draw the background color if needed.
997 r.depth( std::numeric_limits<int>::max() );
998 r.flushFIG( file, transform, colormap );
999 }
1000
1001 // Draw the shapes.
1002 i = shapes.begin();
1003 while ( i != end ) {
1004 // notice << (*i)->name() << " " << (*i)->depth() << '\n';
1005 (*i)->flushFIG( file, transform, colormap );
1006 ++i;
1007 }
1008}
1009
1010
1011void
1012Board::saveSVG( const char * filename, PageSize size, double margin ) const
1013{
1014 saveSVG( filename, pageSizes[size][0], pageSizes[size][1], margin );
1015}
1016
1017void
1018Board::saveSVG( std::ostream &out, PageSize size, double margin ) const
1019{
1020 saveSVG( out, pageSizes[size][0], pageSizes[size][1], margin );
1021}
1022
1023
1024void
1025Board::saveSVG( const char * filename, double pageWidth, double pageHeight, double margin ) const
1026{
1027 std::ofstream file( filename );
1028 saveSVG(file, pageWidth, pageHeight, margin);
1029 file.close();
1030}
1031
1032
1033
1034void
1035Board::saveSVG( std::ostream &file, double pageWidth, double pageHeight, double margin, std::string filename ) const
1036{
1037
1038 TransformSVG transform;
1039 Rect box = boundingBox();
1040 bool clipping = _clippingPath.size() > 2;
1041 if ( clipping )
1042 box = box && _clippingPath.boundingBox();
1043 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
1044
1045 file << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" << std::endl;
1046 file << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"" << std::endl;
1047 file << " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" << std::endl;
1048
1049 if ( pageWidth > 0 && pageHeight > 0 ) {
1050 file << "<svg width=\""
1051 << pageWidth << "mm\" height=\""
1052 << pageHeight << "mm\" " << std::endl;
1053 file << " viewBox=\"0 0 "
1054 << pageWidth * ppmm << " "
1055 << pageHeight * ppmm << "\" " << std::endl;
1056 file << " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" >" << std::endl;
1057 } else {
1058 file << "<svg width=\""
1059 << ( box.width / ppmm ) << "mm"
1060 << "\" height=\""
1061 << ( box.height / ppmm ) << "mm"
1062 << "\" " << std::endl;
1063 file << " viewBox=\"0 0 "
1064 << box.width << " "
1065 << box.height << "\" " << std::endl;
1066 file << " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" >" << std::endl;
1067
1068 }
1069
1070 file << "<desc>" << filename
1071 << ", created with the Board library (Copyleft) 2007 Sebastien Fourey"
1072 << "</desc>" << std::endl;
1073
1074 if ( clipping ) {
1075 file << "<g clip-rule=\"nonzero\">\n"
1076 << " <clipPath id=\"GlobalClipPath\">\n"
1077 << " <path clip-rule=\"evenodd\" d=\"";
1078 _clippingPath.flushSVGCommands( file, transform );
1079 file << "\" />\n";
1080 file << " </clipPath>\n";
1081 file << "<g clip-path=\"url(#GlobalClipPath)\">\n";
1082 }
1083
1084 // Draw the background color if needed.
1087 r.flushSVG( file, transform );
1088 }
1089
1090 // Draw the shapes.
1091 std::vector< Shape* > shapes = _shapes;
1092 stable_sort( shapes.begin(), shapes.end(), shapeGreaterDepth );
1093 std::vector< Shape* >::const_iterator i = shapes.begin();
1094 std::vector< Shape* >::const_iterator end = shapes.end();
1095 while ( i != end ) {
1096 (*i)->flushSVG( file, transform );
1097 ++i;
1098 }
1099
1100 if ( clipping )
1101 file << "</g>\n</g>";
1102 file << "</svg>" << std::endl;
1103
1104}
1105
1106
1107void
1108Board::save( const char * filename, double pageWidth, double pageHeight, double margin ) const
1109{
1110 const char * extension = filename + strlen( filename );
1111 while ( extension > filename && *extension != '.' )
1112 --extension;
1113 if ( !(strcmp( extension, ".eps" )) || !(strcmp( extension, ".EPS" )) ) {
1114 saveEPS( filename, pageWidth, pageHeight, margin );
1115 return;
1116 }
1117 if ( !(strcmp( extension, ".fig" )) || !(strcmp( extension, ".FIG" )) ) {
1118 saveFIG( filename, pageWidth, pageHeight, margin );
1119 return;
1120 }
1121 if ( !(strcmp( extension, ".svg" )) || !(strcmp( extension, ".SVG" )) ) {
1122 saveSVG( filename, pageWidth, pageHeight, margin );
1123 return;
1124 }
1125 if ( !(strcmp( extension, ".tikz" )) || !(strcmp( extension, ".TIKZ" )) ) {
1126 saveTikZ( filename, pageWidth, pageHeight, margin );
1127 return;
1128 }
1129}
1130
1131void
1132Board::save( const char * filename, PageSize size, double margin ) const
1133{
1134 save( filename, pageSizes[size][0], pageSizes[size][1], margin );
1135}
1136
1137#ifdef WITH_CAIRO
1138void
1139Board::saveCairo( const char * filename, CairoType type, PageSize size, double margin ) const
1140{
1141 saveCairo( filename, type, pageSizes[size][0], pageSizes[size][1], margin );
1142}
1143void
1144Board::saveCairo( const char * filename, CairoType type, double pageWidth, double pageHeight, double margin ) const
1145{
1146 cairo_surface_t *surface;
1147 cairo_t *cr;
1148
1149 double cairoWidth, cairoHeight;
1150
1151 TransformCairo transform;
1152 Rect box = boundingBox();
1153
1154 bool clipping = _clippingPath.size() > 2;
1155 if ( clipping )
1156 box = box && _clippingPath.boundingBox();
1157 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
1158
1159 if ( pageWidth > 0 && pageHeight > 0 )
1160 {
1161 cairoWidth = pageWidth;
1162 cairoHeight = pageHeight;
1163 }
1164 else
1165 {
1166 cairoWidth = box.width;
1167 cairoHeight = box.height;
1168 }
1169
1170 switch (type)
1171 {
1172 case CairoPDF:
1173 surface = cairo_pdf_surface_create (filename, cairoWidth, cairoHeight); break;
1174 case CairoPS:
1175 surface = cairo_ps_surface_create (filename, cairoWidth, cairoHeight); break;
1176 case CairoEPS:
1177 surface = cairo_ps_surface_create (filename, cairoWidth, cairoHeight);
1178 cairo_ps_surface_set_eps(surface, true); break;
1179 case CairoSVG:
1180 surface = cairo_svg_surface_create (filename, cairoWidth, cairoHeight); break;
1181 case CairoPNG:
1182 default:
1183 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, (int)cairoWidth, (int)cairoHeight);
1184 }
1185
1186 cr = cairo_create (surface);
1187
1188 /* For 1.0 x 1.0 coordinate space */
1189 //cairo_scale (cr, cairoWidth, cairoHeight);
1190
1191 //temp: http://zetcode.com/tutorials/cairographicstutorial/basicdrawing/
1192 //temp: http://www.graphviz.org/pub/scm/graphviz-cairo/plugin/cairo/gvrender_cairo.c
1193
1194 // Draw the background color if needed.
1197 r.flushCairo( cr, transform );
1198 }
1199
1200 // Draw the shapes.
1201 std::vector< Shape* > shapes = _shapes;
1202 stable_sort( shapes.begin(), shapes.end(), shapeGreaterDepth );
1203 std::vector< Shape* >::const_iterator i = shapes.begin();
1204 std::vector< Shape* >::const_iterator end = shapes.end();
1205 while ( i != end ) {
1206 (*i)->flushCairo( cr, transform );
1207 ++i;
1208 }
1209
1210 if (type==CairoPNG)
1211 cairo_surface_write_to_png (surface, filename);
1212
1213 cairo_destroy (cr);
1214 cairo_surface_destroy (surface);
1215}
1216#endif
1217
1218void
1219Board::saveTikZ( const char * filename, PageSize size, double margin ) const
1220{
1221 saveTikZ( filename, pageSizes[size][0], pageSizes[size][1], margin );
1222}
1223
1224void
1225Board::saveTikZ( std::ostream & out, PageSize size, double margin ) const
1226{
1227 saveTikZ( out, pageSizes[size][0], pageSizes[size][1], margin );
1228}
1229
1230void
1231Board::saveTikZ( const char * filename, double /*pageWidth*/, double pageHeight, double margin ) const
1232{
1233 std::ofstream file( filename );
1234 saveTikZ(file, pageHeight, pageHeight, margin);
1235 file.close();
1236}
1237
1238void
1239Board::saveTikZ( std::ostream &out, double pageWidth, double pageHeight, double margin ) const
1240{
1241 TransformTikZ transform;
1242 Rect box = boundingBox();
1243 bool clipping = _clippingPath.size() > 2;
1244 if ( clipping )
1245 box = box && _clippingPath.boundingBox();
1246 transform.setBoundingBox( box, pageWidth, pageHeight, margin );
1247
1248 out << "\\begin{tikzpicture}[anchor=south west,text depth=0,x={(1pt,0pt)},y={(0pt,-1pt)}]" << std::endl;
1249
1250 if ( clipping ) {
1251 out << "\\clip ";
1252 _clippingPath.flushSVGCommands( out, transform );
1253 out << "\n";
1254 }
1255
1256 // Draw the background color if needed.
1259 r.flushTikZ( out, transform );
1260 }
1261
1262 // Draw the shapes.
1263 std::vector< Shape* > shapes = _shapes;
1264 stable_sort( shapes.begin(), shapes.end(), shapeGreaterDepth );
1265 std::vector< Shape* >::const_iterator i = shapes.begin();
1266 std::vector< Shape* >::const_iterator end = shapes.end();
1267 while ( i != end ) {
1268 (*i)->flushTikZ( out, transform );
1269 ++i;
1270 }
1271
1272 //if ( clipping )
1273 // out << "</g>\n</g>";
1274 out << "\\end{tikzpicture}" << std::endl;
1275}
1276
1277
1278} // namespace LibBoard;
1279
1280
Structure representing an RGB triple with alpha component.
Definition: Color.h:68
Color & setRGBi(const unsigned char aRedValue, const unsigned char aGreenValue, const unsigned char aBlueValue, const unsigned char aAlphaValue=255)
bool valid() const
static const Color None
Definition: Color.h:412
void green(const unsigned char aGreenValue)
void red(const unsigned char aRedValue)
static const Color Black
Definition: Color.h:413
Color & setRGBf(float red, float green, float blue, float alpha=1.0)
Definition: Color.cpp:65
void blue(const unsigned char aBlueValue)
Class for EPS, FIG or SVG drawings.
Definition: Board.h:35
void drawRectangle(double x, double y, double width, double height, int depthValue=-1)
Definition: Board.cpp:417
Board & setFont(const Fonts::Font font, double fontSize)
Definition: Board.cpp:336
Board & setPenColor(const DGtal::Color &color)
Definition: Board.cpp:298
void fillTriangle(double x1, double y1, double x2, double y2, double x3, double y3, int depthValue=-1)
Definition: Board.cpp:609
void setClippingRectangle(double x, double y, double width, double height)
Definition: Board.cpp:728
DGtal::Color _backgroundColor
Definition: Board.h:956
void drawEllipse(double x, double y, double xRadius, double yRadius, int depthValue=-1)
Definition: Board.cpp:482
State _state
Definition: Board.h:955
void drawPolyline(const std::vector< Point > &points, int depthValue=-1)
Definition: Board.cpp:511
Board & setFontSize(double fontSize)
Definition: Board.cpp:344
void saveTikZ(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:1219
void saveFIG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0, bool includeFIGHeader=true) const
Definition: Board.cpp:907
void setClippingPath(const std::vector< Point > &points)
Definition: Board.cpp:739
Board & operator<<(const Shape &shape)
Definition: Board.cpp:133
void drawTriangle(double x1, double y1, double x2, double y2, double x3, double y3, int depthValue=-1)
Definition: Board.cpp:571
void drawQuadraticBezierCurve(double x1, double y1, double x2, double y2, double x3, double y3, int depthValue=-1)
Definition: Board.cpp:384
void fillCircle(double x, double y, double radius, int depthValue=-1)
Definition: Board.cpp:471
void drawLine(double x1, double y1, double x2, double y2, int depthValue=-1)
Definition: Board.cpp:368
void fillPolyline(const std::vector< Point > &points, int depthValue=-1)
Definition: Board.cpp:551
Board & operator=(const Board &other)
Definition: Board.cpp:117
void save(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:1132
Board & setPenColorRGBi(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=255)
Definition: Board.cpp:278
void drawDot(double x, double y, int depthValue=-1)
Definition: Board.cpp:357
static const double Degree
Definition: Board.h:44
void drawClosedPolyline(const std::vector< Point > &points, int depthValue=-1)
Definition: Board.cpp:531
void drawArc(double x, double y, double radius, double angle1, double angle2, bool neg, int depthValue=-1)
Definition: Board.cpp:461
void fillGouraudTriangle(const Point &p1, const DGtal::Color &color1, const Point &p2, const DGtal::Color &color2, const Point &p3, const DGtal::Color &color3, unsigned char divisions=3, int depthValue=-1)
Definition: Board.cpp:647
void drawArrow(double x1, double y1, double x2, double y2, bool filled=true, int depthValue=-1)
Definition: Board.cpp:400
Board & setPenColorRGBf(float red, float green, float blue, float alpha=1.0f)
Definition: Board.cpp:288
void drawCircle(double x, double y, double radius, int depthValue=-1)
Definition: Board.cpp:451
Shape & translate(double dx, double dy)
Definition: Board.cpp:176
void fillRectangle(double x, double y, double width, double height, int depthValue=-1)
Definition: Board.cpp:439
Board translated(double dx, double dy)
Definition: Board.cpp:221
Shape & rotate(double angle, const Point &center)
Definition: Board.cpp:160
void addDuplicates(const Shape &shape, unsigned int times, double dx, double dy, double scale=1.0)
Definition: Board.cpp:767
Board scaled(double sx, double sy)
Definition: Board.cpp:227
void drawText(double x, double y, const char *text, int depthValue=-1)
Definition: Board.cpp:693
Board & setFillColorRGBi(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=255)
Definition: Board.cpp:305
Board & setFillColor(const DGtal::Color &color)
Definition: Board.cpp:322
Board & setLineWidth(double width)
Definition: Board.cpp:329
void fillEllipse(double x, double y, double xRadius, double yRadius, int depthValue=-1)
Definition: Board.cpp:497
void saveEPS(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:805
void backgroundColor(const DGtal::Color &color)
Definition: Board.cpp:351
void drawImage(std::string filename, double x, double y, double width, double height, int depthValue=-1, double alpha=1.0)
Definition: Board.cpp:428
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:1012
Board & setFillColorRGBf(float red, float green, float blue, float alpha=1.0f)
Definition: Board.cpp:315
Board(const DGtal::Color &backgroundColor=DGtal::Color::None)
Definition: Board.cpp:104
void setUnit(Unit unit)
Definition: Board.cpp:240
Path _clippingPath
Definition: Board.h:957
Shape & scale(double sx, double sy)
Definition: Board.cpp:184
Board rotated(double angle, const Point &center)
Definition: Board.cpp:209
void drawBoundingBox(int depthValue=-1)
Definition: Board.cpp:710
void saveCairo(const char *filename, CairoType type=CairoPNG, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:1139
bool shapeGreaterDepth(const Shape *s1, const Shape *s2)
Definition: Shapes.cpp:95
void secured_ctime(char *str, const time_t *t, size_t count)
A line between two points with an arrow at one extremity.
Definition: Board/Shapes.h:665
double unit(const double &x)
Definition: Board.h:951
DGtal::Color penColor
Definition: Board.h:941
Shape::LineJoin lineJoin
Definition: Board.h:946
Shape::LineCap lineCap
Definition: Board.h:945
Fonts::Font font
Definition: Board.h:947
Shape::LineStyle lineStyle
Definition: Board.h:944
DGtal::Color fillColor
Definition: Board.h:942
A line between two points.
Definition: Board/Shapes.h:398
A triangle with shaded filling according to colors given for each vertex.
Used to draw image in figure.
A line between two points.
Definition: Board/Shapes.h:534
A path, according to Postscript and SVG definition.
Definition: Path.h:43
unsigned int size() const
Definition: Path.h:249
void clear()
Definition: Path.h:231
Path & pop_back()
Definition: Path.cpp:22
Path & scale(double sx, double sy)
Definition: Path.cpp:108
Point center() const
Definition: Path.cpp:36
void setClosed(bool closed)
Definition: Path.h:255
Rect boundingBox() const
Definition: Path.cpp:272
Path & translate(double dx, double dy)
Definition: Path.cpp:81
void flushPostscript(std::ostream &stream, const TransformEPS &transform) const
Definition: Path.cpp:154
void flushSVGCommands(std::ostream &stream, const TransformSVG &transform) const
Definition: Path.cpp:193
Path & rotate(double angle, const Point &center)
Definition: Path.cpp:43
Struct representing a 2D point.
Definition: Point.h:27
double y
Definition: Point.h:30
double x
Definition: Point.h:29
A polygonal line described by a series of 2D points.
Definition: Board/Shapes.h:765
A quadratic Bezier curve having 3 control points. NB. It is also a parabola arc.
Struct representing a rectangle on the plane.
Definition: Rect.h:26
double height
Definition: Rect.h:31
double width
Definition: Rect.h:30
double left
Definition: Rect.h:28
double top
Definition: Rect.h:29
A group of shapes.
Definition: ShapeList.h:28
void addShape(const Shape &shape, double scaleFactor)
Definition: ShapeList.cpp:122
Shape & rotate(double angle, const Point &center)
Definition: ShapeList.cpp:205
std::vector< Shape * > _shapes
Definition: ShapeList.h:169
Shape & translate(double dx, double dy)
Definition: ShapeList.cpp:236
Shape & scale(double sx, double sy)
Definition: ShapeList.cpp:254
Point center() const
Definition: ShapeList.cpp:192
Rect boundingBox() const
Definition: ShapeList.cpp:379
ShapeList & clear()
Definition: ShapeList.cpp:43
Abstract structure for a 2D shape.
Definition: Board/Shapes.h:58
virtual Shape & scale(double sx, double sy)=0
virtual Shape & translate(double dx, double dy)=0
virtual Shape * clone() const =0
virtual Shape & rotate(double angle, const Point &center)=0
A piece of text.
Structure representing a scaling and translation suitable for an Cairo output.
Definition: Transforms.h:112
Structure representing a scaling and translation suitable for an EPS output.
Definition: Transforms.h:59
void setBoundingBox(const Rect &rect, const double pageWidth, const double pageHeight, const double margin)
Definition: Transforms.cpp:68
Structure representing a scaling and translation suitable for an XFig output.
Definition: Transforms.h:73
Structure representing a scaling and translation suitable for an SVG output.
Definition: Transforms.h:95
Structure representing a scaling and translation suitable for an TikZ output.
Definition: Transforms.h:129