1
// Copyright (C) 2004 Pino Toscano <toscano.pino@tiscali.it>
2
// Copyright (C) 2010,2011 Raoul Bourquin (asymptote exporter part)
4
// This program is free software; you can redistribute it and/or
5
// modify it under the terms of the GNU General Public License
6
// as published by the Free Software Foundation; either version 2
7
// of the License, or (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
#include "latexexporter.h"
20
#include "asyexporterimpvisitor.h"
21
#include "latexexporteroptions.h"
23
#include "../kig/kig_document.h"
24
#include "../kig/kig_part.h"
25
#include "../kig/kig_view.h"
26
#include "../misc/common.h"
27
#include "../misc/goniometry.h"
28
#include "../misc/kigfiledialog.h"
29
#include "../misc/rect.h"
30
#include "../objects/circle_imp.h"
31
#include "../objects/cubic_imp.h"
32
#include "../objects/bezier_imp.h"
33
#include "../objects/curve_imp.h"
34
#include "../objects/line_imp.h"
35
#include "../objects/locus_imp.h"
36
#include "../objects/object_drawer.h"
37
#include "../objects/object_holder.h"
38
#include "../objects/object_imp.h"
39
#include "../objects/other_imp.h"
40
#include "../objects/point_imp.h"
41
#include "../objects/polygon_imp.h"
42
#include "../objects/text_imp.h"
47
#include <qcheckbox.h>
50
#include <qtextstream.h>
53
#include <kmessagebox.h>
55
#include <config-kig.h>
58
#define KDE_TRUNC(a) trunc(a)
60
#define KDE_TRUNC(a) rint(a)
68
LatexExporter::~LatexExporter()
72
QString LatexExporter::exportToStatement() const
74
return i18n( "Export to &Latex..." );
77
QString LatexExporter::menuEntryName() const
79
return i18n( "&Latex..." );
82
QString LatexExporter::menuIcon() const
87
class PSTricksExportImpVisitor
88
: public ObjectImpVisitor
91
ObjectHolder* mcurobj;
94
std::vector<ColorMap> mcolors;
97
void visit( ObjectHolder* obj );
98
void mapColor( const QColor& color );
100
PSTricksExportImpVisitor( QTextStream& s, const KigWidget& w )
101
: mstream( s ), mw( w ), msr( mw.showingRect() )
104
void visit( const LineImp* imp );
105
void visit( const PointImp* imp );
106
void visit( const TextImp* imp );
107
void visit( const AngleImp* imp );
108
void visit( const VectorImp* imp );
109
void visit( const LocusImp* imp );
110
void visit( const CircleImp* imp );
111
void visit( const ConicImp* imp );
112
void visit( const CubicImp* imp );
113
void visit( const SegmentImp* imp );
114
void visit( const RayImp* imp );
115
void visit( const ArcImp* imp );
116
void visit( const FilledPolygonImp* imp );
117
void visit( const ClosedPolygonalImp* imp );
118
void visit( const OpenPolygonalImp* imp );
119
void visit( const BezierImp* imp );
120
void visit( const RationalBezierImp* imp );
126
* Converts Kig coords to pstrick coord system and sends them to stream
127
* using the format: (xcoord,ycoord)
129
void emitCoord( const Coordinate& c );
131
* Draws a line (segment) or a vector if vector is true.
133
void emitLine( const Coordinate& a, const Coordinate& b, const int width,
134
const Qt::PenStyle s, bool vector = false );
136
* Sends a new line character ( \n ) to stream.
140
* Searches if a color is already mapped into mcolors, and returns its
141
* index or -1 if not found.
143
int findColor( const QColor& c );
145
* Use to convert a dimension "on the screen" to a dimension wrt.
146
* Kig coordinate system.
148
double dimRealToCoord( int dim );
150
* Converts a pen style into latex style string.
152
QString writeStyle( Qt::PenStyle style );
154
* Plots a generic curve though its points calc'ed with getPoint.
156
void plotGenericCurve( const CurveImp* imp );
159
void PSTricksExportImpVisitor::emitCoord( const Coordinate& c )
161
mstream << "(" << c.x - msr.left() << "," << c.y - msr.bottom() << ")";
164
void PSTricksExportImpVisitor::emitLine( const Coordinate& a, const Coordinate& b,
165
const int width, const Qt::PenStyle s,
168
mstream << "\\psline[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0
169
<< "," << writeStyle( s );
171
mstream << ",arrowscale=3,arrowinset=1.3";
180
void PSTricksExportImpVisitor::newLine()
185
int PSTricksExportImpVisitor::findColor( const QColor& c )
187
for ( uint i = 0; i < mcolors.size(); ++i )
189
if ( c == mcolors[i].color )
195
void PSTricksExportImpVisitor::mapColor( const QColor& color )
197
if ( findColor( color ) == -1 )
200
newcolor.color = color;
201
QString tmpname = color.name();
202
tmpname.remove( '#' );
203
newcolor.name = tmpname;
204
mcolors.push_back( newcolor );
205
mstream << "\\newrgbcolor{" << tmpname << "}{"
206
<< color.red() / 255.0 << " " << color.green() / 255.0 << " "
207
<< color.blue() / 255.0 << "}\n";
211
double PSTricksExportImpVisitor::dimRealToCoord( int dim )
213
QRect qr( 0, 0, dim, dim );
214
Rect r = mw.screenInfo().fromScreen( qr );
215
return fabs( r.width() );
218
QString PSTricksExportImpVisitor::writeStyle( Qt::PenStyle style )
220
QString ret( "linestyle=" );
221
if ( style == Qt::DashLine )
223
else if ( style == Qt::DotLine )
224
ret += "dotted,dotsep=2pt";
230
void PSTricksExportImpVisitor::plotGenericCurve( const CurveImp* imp )
232
int width = mcurobj->drawer()->width();
233
if ( width == -1 ) width = 1;
235
QString prefix = QString( "\\pscurve[linecolor=%1,linewidth=%2,%3]" )
237
.arg( width / 100.0 )
238
.arg( writeStyle( mcurobj->drawer()->style() ) );
240
std::vector< std::vector< Coordinate > > coordlist;
241
coordlist.push_back( std::vector< Coordinate >() );
245
Coordinate prev = Coordinate::invalidCoord();
246
for ( double i = 0.0; i <= 1.0; i += 0.005 )
248
c = imp->getPoint( i, mw.document() );
251
if ( coordlist[curid].size() > 0 )
253
coordlist.push_back( std::vector< Coordinate >() );
255
prev = Coordinate::invalidCoord();
259
if ( ! ( ( fabs( c.x ) <= 1000 ) && ( fabs( c.y ) <= 1000 ) ) )
261
// if there's too much distance between this coordinate and the previous
262
// one, then it's another piece of curve not joined with the rest
263
if ( prev.valid() && ( c.distance( prev ) > 4.0 ) )
265
coordlist.push_back( std::vector< Coordinate >() );
268
coordlist[curid].push_back( c );
271
// special case for ellipse
272
if ( const ConicImp* conic = dynamic_cast< const ConicImp* >( imp ) )
274
// if ellipse, close its path
275
if ( conic->conicType() == 1 && coordlist.size() == 1 && coordlist[0].size() > 1 )
277
coordlist[0].push_back( coordlist[0][0] );
280
for ( uint i = 0; i < coordlist.size(); ++i )
282
uint s = coordlist[i].size();
283
// there's no point in draw curves empty or with only one point
288
for ( uint j = 0; j < s; ++j )
289
emitCoord( coordlist[i][j] );
294
void PSTricksExportImpVisitor::visit( ObjectHolder* obj )
296
if ( ! obj->drawer()->shown() )
298
const int id = findColor( obj->drawer()->color() );
301
mcurcolorid = mcolors[id].name;
303
obj->imp()->visit( this );
306
void PSTricksExportImpVisitor::visit( const LineImp* imp )
308
Coordinate a = imp->data().a;
309
Coordinate b = imp->data().b;
310
calcBorderPoints( a, b, msr );
312
int width = mcurobj->drawer()->width();
313
if ( width == -1 ) width = 1;
315
emitLine( a, b, width, mcurobj->drawer()->style() );
318
void PSTricksExportImpVisitor::visit( const PointImp* imp )
320
int width = mcurobj->drawer()->width();
321
if ( width == -1 ) width = 5;
324
mstream << "\\psdots[linecolor=" << mcurcolorid
325
<< ",dotscale=" << width << ",dotstyle=";
326
const int ps = mcurobj->drawer()->pointStyle();
327
QString pss( "*,fillstyle=solid,fillcolor=" + mcurcolorid );
329
pss = "o,fillstyle=none";
331
pss = "square*,fillstyle=solid,fillcolor=" + mcurcolorid;
333
pss = "square,fillstyle=none";
335
pss = "+,dotangle=45";
336
mstream << pss << "]";
337
emitCoord( imp->coordinate() );
341
void PSTricksExportImpVisitor::visit( const TextImp* imp )
343
// FIXME: support multiline texts...
344
mstream << "\\rput[tl]";
345
emitCoord( imp->coordinate() );
349
if ( imp->hasFrame() )
351
mstream << " \\psframebox[linecolor=c5c2c5,linewidth=0.01"
352
<< ",fillstyle=solid,fillcolor=ffffde]"
353
<< "{" << imp->text() << "}";
357
mstream << imp->text();
364
void PSTricksExportImpVisitor::visit( const AngleImp* imp )
366
const Coordinate center = imp->point();
367
const double radius = dimRealToCoord( 50 ) * unit;
368
double startangle = imp->startAngle();
369
double endangle = startangle + imp->angle();
370
// if ( startangle > M_PI )
371
// startangle -= 2 * M_PI;
372
startangle = Goniometry::convert( startangle, Goniometry::Rad, Goniometry::Deg );
373
// if ( endangle > 2 * M_PI )
374
// endangle -= 2 * M_PI;
375
endangle = Goniometry::convert( endangle, Goniometry::Rad, Goniometry::Deg );
376
int width = mcurobj->drawer()->width();
377
if ( width == -1 ) width = 1;
379
mstream << "\\psarc[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0
380
<< "," << writeStyle( mcurobj->drawer()->style() ) << ",arrowscale=3,arrowinset=0]{->}";
382
mstream << "{" << radius << "}{" << startangle << "}{" << endangle << "}";
386
void PSTricksExportImpVisitor::visit( const VectorImp* imp )
388
Coordinate a = imp->data().a;
389
Coordinate b = imp->data().b;
391
int width = mcurobj->drawer()->width();
392
if ( width == -1 ) width = 1;
394
emitLine( a, b, width, mcurobj->drawer()->style(), true );
397
void PSTricksExportImpVisitor::visit( const LocusImp* imp )
399
plotGenericCurve( imp );
402
void PSTricksExportImpVisitor::visit( const CircleImp* imp )
404
int width = mcurobj->drawer()->width();
405
if ( width == -1 ) width = 1;
407
mstream << "\\pscircle[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0
408
<< "," << writeStyle( mcurobj->drawer()->style() ) << "]";
409
emitCoord( imp->center() );
410
mstream << "{" << imp->radius() * unit << "}";
414
void PSTricksExportImpVisitor::visit( const ConicImp* imp )
416
plotGenericCurve( imp );
419
void PSTricksExportImpVisitor::visit( const CubicImp* )
421
// FIXME: cubic are not drawn correctly with plotGenericCurve
422
// plotGenericCurve( imp );
425
void PSTricksExportImpVisitor::visit( const SegmentImp* imp )
427
Coordinate a = imp->data().a;
428
Coordinate b = imp->data().b;
430
int width = mcurobj->drawer()->width();
431
if ( width == -1 ) width = 1;
433
emitLine( a, b, width, mcurobj->drawer()->style() );
436
void PSTricksExportImpVisitor::visit( const RayImp* imp )
438
Coordinate a = imp->data().a;
439
Coordinate b = imp->data().b;
440
calcRayBorderPoints( a, b, msr );
442
int width = mcurobj->drawer()->width();
443
if ( width == -1 ) width = 1;
445
emitLine( a, b, width, mcurobj->drawer()->style() );
448
void PSTricksExportImpVisitor::visit( const ArcImp* imp )
450
const Coordinate center = imp->center();
451
const double radius = imp->radius() * unit;
452
double startangle = imp->startAngle();
453
double endangle = startangle + imp->angle();
454
// if ( startangle > M_PI )
455
// startangle -= 2 * M_PI;
456
startangle = Goniometry::convert( startangle, Goniometry::Rad, Goniometry::Deg );
457
// if ( endangle > M_PI )
458
// endangle -= 2 * M_PI;
459
endangle = Goniometry::convert( endangle, Goniometry::Rad, Goniometry::Deg );
460
int width = mcurobj->drawer()->width();
461
if ( width == -1 ) width = 1;
463
mstream << "\\psarc[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0
464
<< "," << writeStyle( mcurobj->drawer()->style() ) << "]";
466
mstream << "{" << radius << "}{" << startangle << "}{" << endangle << "}";
470
void PSTricksExportImpVisitor::visit( const FilledPolygonImp* imp )
472
int width = mcurobj->drawer()->width();
473
if ( width == -1 ) width = 1;
475
mstream << "\\pspolygon[linecolor=" << mcurcolorid << ",linewidth=0"
476
<< "," << writeStyle( mcurobj->drawer()->style() )
477
<< ",hatchcolor=" << mcurcolorid << ",hatchwidth=0.5pt,hatchsep=0.5pt"
478
<< ",fillcolor=" << mcurcolorid << ",fillstyle=crosshatch]";
480
std::vector<Coordinate> pts = imp->points();
481
for ( uint i = 0; i < pts.size(); i++ )
488
void PSTricksExportImpVisitor::visit(const ClosedPolygonalImp* imp)
490
int width = mcurobj->drawer()->width();
491
if ( width == -1 ) width = 1;
493
mstream << "\\pspolygon[linecolor=" << mcurcolorid << ",linewidth=0"
494
<< "," << writeStyle( mcurobj->drawer()->style() ) << ']';
496
std::vector<Coordinate> pts = imp->points();
497
for ( uint i = 0; i < pts.size(); i++ )
504
void PSTricksExportImpVisitor::visit(const OpenPolygonalImp* imp)
506
int width = mcurobj->drawer()->width();
507
if ( width == -1 ) width = 1;
509
mstream << "\\psline[linecolor=" << mcurcolorid << ",linewidth=0"
510
<< "," << writeStyle( mcurobj->drawer()->style() ) << ']';
512
std::vector<Coordinate> pts = imp->points();
513
for ( uint i = 0; i < pts.size(); i++ )
520
// TODO: Just a quick fix, improve when reviewing PSTricks exporter
521
void PSTricksExportImpVisitor::visit(const BezierImp* imp)
523
plotGenericCurve(imp);
526
// TODO: Just a quick fix, improve when reviewing PSTricks exporter
527
void PSTricksExportImpVisitor::visit(const RationalBezierImp* imp)
529
plotGenericCurve(imp);
533
class TikZExportImpVisitor
534
: public ObjectImpVisitor
536
QTextStream& mstream;
537
ObjectHolder* mcurobj;
540
std::vector<ColorMap> mcolors;
543
void visit( ObjectHolder* obj );
544
void mapColor( const QColor& color );
546
TikZExportImpVisitor( QTextStream& s, const KigWidget& w )
547
: mstream( s ), mw( w ), msr( mw.showingRect() )
550
void visit( const LineImp* imp );
551
void visit( const PointImp* imp );
552
void visit( const TextImp* imp );
553
void visit( const AngleImp* imp );
554
void visit( const VectorImp* imp );
555
void visit( const LocusImp* imp );
556
void visit( const CircleImp* imp );
557
void visit( const ConicImp* imp );
558
void visit( const CubicImp* imp );
559
void visit( const SegmentImp* imp );
560
void visit( const RayImp* imp );
561
void visit( const ArcImp* imp );
562
void visit( const FilledPolygonImp* imp );
563
void visit( const ClosedPolygonalImp* imp );
564
void visit( const OpenPolygonalImp* imp );
565
void visit( const BezierImp* imp);
566
void visit( const RationalBezierImp* imp);
572
* Converts Kig coords to pstrick coord system and sends them to stream
573
* using the format: (xcoord,ycoord)
575
void emitCoord( const Coordinate& c );
577
* Draws a line (segment) or a vector if vector is true.
579
void emitLine( const Coordinate& a, const Coordinate& b, const int width,
580
const Qt::PenStyle s, bool vector = false );
582
* Sends a new line character ( \n ) to stream.
586
* Searches if a color is already mapped into mcolors, and returns its
587
* index or -1 if not found.
589
int findColor( const QColor& c );
591
* Use to convert a dimension "on the screen" to a dimension wrt.
592
* Kig coordinate system.
594
double dimRealToCoord( int dim );
596
* Converts a pen style into latex style string.
598
QString writeStyle( Qt::PenStyle style );
600
* Plots a generic curve though its points calc'ed with getPoint.
602
void plotGenericCurve( const CurveImp* imp );
605
void TikZExportImpVisitor::emitCoord( const Coordinate& c )
607
mstream << '(' << c.x << ',' << c.y << ')';
610
void TikZExportImpVisitor::emitLine( const Coordinate& a, const Coordinate& b,
611
const int width, const Qt::PenStyle s,
616
mstream << "\\draw[->,color=" << mcurcolorid << ",line width=" << width <<']';
620
mstream << "\\draw[color=" << mcurcolorid << ",line width=" << width << ']';
629
void TikZExportImpVisitor::newLine()
635
int TikZExportImpVisitor::findColor( const QColor& c )
637
for ( uint i = 0; i < mcolors.size(); ++i )
639
if ( c == mcolors[i].color )
645
void TikZExportImpVisitor::mapColor( const QColor& color )
647
if ( findColor( color ) == -1 )
650
newcolor.color = color;
651
QString tmpname = color.name();
652
tmpname.remove( '#' );
653
newcolor.name = tmpname;
654
mcolors.push_back( newcolor );
655
mstream << "\\definecolor{" << tmpname << "}{RGB}{" << color.red() << ',' << color.green() << ',' << color.blue() << "}\n";
659
QString TikZExportImpVisitor::writeStyle( Qt::PenStyle style )
663
ret += "line style=";
664
if ( style == Qt::DashLine )
666
else if ( style == Qt::DotLine )
667
ret += "dotted,dotsep=2pt";
674
void TikZExportImpVisitor::plotGenericCurve( const CurveImp* imp )
676
int width = mcurobj->drawer()->width();
677
if ( width == -1 ) width = 1;
679
std::vector< std::vector< Coordinate > > coordlist;
680
coordlist.push_back( std::vector< Coordinate >() );
684
Coordinate prev = Coordinate::invalidCoord();
685
for ( double i = 0.0; i <= 1.0; i += 0.005 )
687
c = imp->getPoint( i, mw.document() );
690
if ( coordlist[curid].size() > 0 )
692
coordlist.push_back( std::vector< Coordinate >() );
694
prev = Coordinate::invalidCoord();
698
if ( ! ( ( fabs( c.x ) <= 1000 ) && ( fabs( c.y ) <= 1000 ) ) )
700
// if there's too much distance between this coordinate and the previous
701
// one, then it's another piece of curve not joined with the rest
702
if ( prev.valid() && ( c.distance( prev ) > 4.0 ) )
704
coordlist.push_back( std::vector< Coordinate >() );
707
coordlist[curid].push_back( c );
711
for ( uint i = 0; i < coordlist.size(); ++i )
713
uint s = coordlist[i].size();
714
// there's no point in draw curves empty or with only one point
718
mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << ']';
719
for ( uint j = 0; j < s; ++j )
721
emitCoord( coordlist[i][j] );
732
void TikZExportImpVisitor::visit( ObjectHolder* obj )
734
mstream << "%% " << obj->imp()->type()->translatedName();
736
if ( ! obj->drawer()->shown() )
738
const int id = findColor( obj->drawer()->color() );
741
mcurcolorid = mcolors[id].name;
743
obj->imp()->visit( this );
746
void TikZExportImpVisitor::visit( const LineImp* imp )
748
Coordinate a = imp->data().a;
749
Coordinate b = imp->data().b;
750
calcBorderPoints( a, b, msr );
752
int width = mcurobj->drawer()->width();
753
if ( width == -1 ) width = 1;
755
emitLine( a, b, width, mcurobj->drawer()->style() );
758
void TikZExportImpVisitor::visit( const PointImp* imp )
760
int width = mcurobj->drawer()->width();
761
if ( width == -1 ) width = 1;
763
mstream << "\\path [fill=" << mcurcolorid << "] ";
764
emitCoord (imp->coordinate());
765
mstream << " circle (" << width << "pt)";
769
void TikZExportImpVisitor::visit( const TextImp* imp )
771
mstream << "\\node ";
774
mstream << "[rectangle,draw] ";
777
emitCoord(imp->coordinate());
778
mstream << " {" << imp->text() << "}";
782
void TikZExportImpVisitor::visit( const AngleImp* imp )
784
int width = mcurobj->drawer()->width();
785
if ( width == -1 ) width = 1;
787
double start = Goniometry::convert( imp->startAngle(), Goniometry::Rad, Goniometry::Deg );
788
double end = Goniometry::convert( imp->startAngle() + imp->angle(), Goniometry::Rad, Goniometry::Deg );
790
mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << ']';
791
emitCoord(imp->point());
792
mstream << " +(" << start << ':' << radius << ')';
793
mstream << " arc (" << start << ':' << end << ':' << radius << ')';
797
void TikZExportImpVisitor::visit( const VectorImp* imp )
799
Coordinate a = imp->data().a;
800
Coordinate b = imp->data().b;
802
int width = mcurobj->drawer()->width();
803
if ( width == -1 ) width = 1;
805
emitLine( a, b, width, mcurobj->drawer()->style(), true );
808
void TikZExportImpVisitor::visit( const LocusImp* imp )
810
plotGenericCurve( imp );
813
void TikZExportImpVisitor::visit( const CircleImp* imp )
815
int width = mcurobj->drawer()->width();
816
if ( width == -1 ) width = 1;
818
mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
819
emitCoord( imp->center() );
820
mstream << " circle (" << imp->radius() << ')';
824
void TikZExportImpVisitor::visit( const ConicImp* imp )
826
plotGenericCurve(imp);
829
void TikZExportImpVisitor::visit( const CubicImp* imp )
831
plotGenericCurve(imp);
834
void TikZExportImpVisitor::visit( const SegmentImp* imp )
836
Coordinate a = imp->data().a;
837
Coordinate b = imp->data().b;
839
int width = mcurobj->drawer()->width();
840
if ( width == -1 ) width = 1;
842
emitLine( a, b, width, mcurobj->drawer()->style() );
845
void TikZExportImpVisitor::visit( const RayImp* imp )
847
Coordinate a = imp->data().a;
848
Coordinate b = imp->data().b;
849
calcRayBorderPoints( a, b, msr );
851
int width = mcurobj->drawer()->width();
852
if ( width == -1 ) width = 1;
854
emitLine( a, b, width, mcurobj->drawer()->style() );
857
void TikZExportImpVisitor::visit( const ArcImp* imp )
859
int width = mcurobj->drawer()->width();
860
if ( width == -1 ) width = 1;
862
double start = Goniometry::convert( imp->startAngle(), Goniometry::Rad, Goniometry::Deg );
863
double end = Goniometry::convert( imp->startAngle() + imp->angle(), Goniometry::Rad, Goniometry::Deg );
864
double radius = imp->radius();
865
mstream << "\\draw [color=" << mcurcolorid << ",line width=" << width << ']';
866
emitCoord(imp->center());
867
mstream << " +(" << start << ':' << radius << ')';
868
mstream << " arc (" << start << ':' << end << ':' << radius << ")";
872
void TikZExportImpVisitor::visit( const FilledPolygonImp* imp )
874
int width = mcurobj->drawer()->width();
875
if ( width == -1 ) width = 1;
877
mstream << "\\path [fill,color=" << mcurcolorid << ",line width=" << width << "] ";
879
std::vector<Coordinate> pts = imp->points();
880
for ( uint i = 0; i < pts.size(); i++ )
890
void TikZExportImpVisitor::visit ( const ClosedPolygonalImp* imp )
892
int width = mcurobj->drawer()->width();
893
if ( width == -1 ) width = 1;
895
mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
897
std::vector<Coordinate> pts = imp->points();
898
for ( uint i = 0; i < pts.size(); i++ )
907
void TikZExportImpVisitor::visit ( const OpenPolygonalImp* imp )
909
int width = mcurobj->drawer()->width();
910
if ( width == -1 ) width = 1;
912
mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
914
std::vector<Coordinate> pts = imp->points();
915
for ( uint i = 0; i < pts.size(); i++ )
918
if (i < pts.size() - 1)
926
void TikZExportImpVisitor::visit(const BezierImp* imp)
928
int width = mcurobj->drawer()->width();
929
if ( width == -1 ) width = 1;
931
std::vector<Coordinate> pts = imp->points();
935
// Formula for cubic control points
936
// CP1 = QP0 + 2/3 *(QP1-QP0)
937
// CP2 = CP1 + 1/3 *(QP2-QP0)
938
// TODO: Improve emitCoords as in asy exporter
939
mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
940
emitCoord(pts.at(0));
941
mstream << ".. controls ";
943
emitCoord(pts.at(0));
945
emitCoord(pts.at(1));
947
emitCoord(pts.at(0));
951
emitCoord(pts.at(0));
953
emitCoord(pts.at(1));
955
emitCoord(pts.at(0));
957
emitCoord(pts.at(2));
959
emitCoord(pts.at(0));
962
emitCoord(pts.at(2));
966
mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
967
emitCoord(pts.front());
968
mstream << ".. controls ";
969
emitCoord(pts.at(1));
971
emitCoord(pts.at(2));
973
emitCoord(pts.back());
977
plotGenericCurve(imp);
982
// TODO: Just a quick fix, improve when reviewing TikZ exporter
983
void TikZExportImpVisitor::visit(const RationalBezierImp* imp)
985
plotGenericCurve(imp);
989
void LatexExporter::run( const KigPart& doc, KigWidget& w )
991
KigFileDialog* kfd = new KigFileDialog(
992
QString(), i18n( "*.tex|Latex Documents (*.tex)" ),
993
i18n( "Export as Latex" ), &w );
994
kfd->setOptionCaption( i18n( "Latex Options" ) );
995
LatexExporterOptions* opts = new LatexExporterOptions( 0L );
996
kfd->setOptionsWidget( opts );
998
opts->setGrid( doc.document().grid() );
999
opts->setAxes( doc.document().axes() );
1000
opts->setExtraFrame( false );
1002
KConfigGroup cg = KGlobal::config()->group("Latex Exporter");
1004
int fmt = cg.readEntry<int>("OutputFormat", LatexExporterOptions::PSTricks);
1005
if (fmt > -1 && fmt < LatexExporterOptions::FormatCount)
1007
opts->setFormat((LatexExporterOptions::LatexOutputFormat)fmt);
1009
opts->setStandalone(cg.readEntry("Standalone", true));
1014
QString file_name = kfd->selectedFile();
1015
bool showgrid = opts->showGrid();
1016
bool showaxes = opts->showAxes();
1017
bool showframe = opts->showExtraFrame();
1018
LatexExporterOptions::LatexOutputFormat format = opts->format();
1019
bool standalone = opts->standalone();
1024
cg.writeEntry("OutputFormat", (int)format);
1025
cg.writeEntry("Standalone", standalone);
1027
QFile file( file_name );
1028
if ( ! file.open( QIODevice::WriteOnly ) )
1030
KMessageBox::sorry( &w, i18n( "The file \"%1\" could not be opened. Please "
1031
"check if the file permissions are set correctly." ,
1036
QTextStream stream( &file );
1037
std::vector<ObjectHolder*> os = doc.document().objects();
1039
if (format == LatexExporterOptions::PSTricks)
1043
stream << "\\documentclass[a4paper]{minimal}\n";
1044
// stream << "\\usepackage[latin1]{inputenc}\n";
1045
stream << "\\usepackage{pstricks}\n";
1046
stream << "\\usepackage{pst-plot}\n";
1047
stream << "\\author{Kig " << KIGVERSION << "}\n";
1048
stream << "\\begin{document}\n";
1051
const double bottom = w.showingRect().bottom();
1052
const double left = w.showingRect().left();
1053
const double height = w.showingRect().height();
1054
const double width = w.showingRect().width();
1057
// TODO: calculating aspect ratio...
1058
if ( 297 / 210 >= height / width )
1063
const double tmpwidth = 15.0;
1064
const double xunit = tmpwidth / width;
1065
const double yunit = xunit;
1067
stream << "\\begin{pspicture*}(0,0)(" << tmpwidth << "," << yunit * height << ")\n";
1068
stream << "\\psset{xunit=" << xunit << "}\n";
1069
stream << "\\psset{yunit=" << yunit << "}\n";
1071
PSTricksExportImpVisitor visitor( stream, w );
1072
visitor.unit = xunit;
1074
for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
1075
i != os.end(); ++i )
1077
if ( ! ( *i )->shown() ) continue;
1078
visitor.mapColor( ( *i )->drawer()->color() );
1080
visitor.mapColor( QColor( 255, 255, 222 ) ); // ffffde - text label background
1081
visitor.mapColor( QColor( 197, 194, 197 ) ); // c5c2c5 - text label border line
1082
visitor.mapColor( QColor( 160, 160, 164 ) ); // a0a0a4 - axes color
1083
visitor.mapColor( QColor( 192, 192, 192 ) ); // c0c0c0 - grid color
1088
stream << "\\psframe[linecolor=black,linewidth=0.02]"
1090
<< "(" << width << "," << height << ")"
1097
// vertical lines...
1098
double startingpoint = - left - 1 + static_cast<int>( KDE_TRUNC( left ) );
1099
for ( double i = startingpoint; i < width; ++i )
1101
stream << "\\psline[linecolor=c0c0c0,linewidth=0.01,linestyle=dashed]"
1102
<< "(" << i << ",0)"
1103
<< "(" << i << "," << height << ")"
1107
// horizontal lines...
1108
startingpoint = - bottom - 1 + static_cast<int>( KDE_TRUNC( bottom ) );
1109
for ( double i = startingpoint; i < height; ++i )
1111
stream << "\\psline[linecolor=c0c0c0,linewidth=0.01,linestyle=dashed]"
1112
<< "(0," << i << ")"
1113
<< "(" << width << "," << i << ")"
1121
stream << "\\psaxes[linecolor=a0a0a4,linewidth=0.03,ticks=none,arrowinset=0]{->}"
1122
<< "(" << -left << "," << -bottom << ")"
1124
<< "(" << width << "," << height << ")"
1128
for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
1129
i != os.end(); ++i )
1131
visitor.visit( *i );
1134
stream << "\\end{pspicture*}\n";
1137
stream << "\\end{document}\n";
1140
else if (format == LatexExporterOptions::TikZ)
1144
stream << "\\documentclass[a4paper]{minimal}\n";
1145
// stream << "\\usepackage[latin1]{inputenc}\n";
1146
stream << "\\usepackage{tikz}\n";
1147
stream << "\\usetikzlibrary{calc}\n";
1150
stream << "\\tikzset{kig grid/.style=draw,help lines}\n";
1154
stream << "\\tikzset{kig axes/.style=draw,help lines,->}\n";
1158
stream << "\\tikzset{kig frame/.style=draw,black}\n";
1160
stream << "\\author{Kig " << KIGVERSION << "}\n";
1161
stream << "\\begin{document}\n";
1163
TikZExportImpVisitor visitor( stream, w );
1165
Rect frameRect = w.showingRect();
1167
for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
1168
i != os.end(); ++i )
1170
if ( ! ( *i )->shown() ) continue;
1171
visitor.mapColor( ( *i )->drawer()->color() );
1174
double size = qMax(frameRect.height(),frameRect.width());
1175
double scale = (size == 0) ? 1 : 10/size;
1177
stream << "\\begin{tikzpicture}";
1178
stream << "[scale=" << scale << "]\n";
1179
double gLeft = frameRect.left();
1180
double gBottom = frameRect.bottom();
1181
double gRight = frameRect.right();
1182
double gTop = frameRect.top();
1184
stream << "\\clip (" << gLeft << ',' << gBottom << ") rectangle (" << gRight << ',' << gTop << ");\n";
1188
stream << "\\path [kig frame] (" << gLeft << ',' << gBottom << ") rectangle (" << gRight << ',' << gTop << ");\n";
1192
stream << "\\path [kig grid] ("<< floor(qMin(0.0,gRight)) << ',' << floor(qMin(0.0,gTop))
1193
<< ") grid (" << ceil(qMax(0.0,gRight)) << ',' << ceil(qMax(0.0,gTop)) << ");\n";
1194
stream << "\\path [kig grid] ("<< floor(qMin(0.0,gLeft)) << ',' << floor(qMin(0.0,gTop))
1195
<< ") grid (" << ceil(qMax(0.0,gLeft)) << ',' << ceil(qMax(0.0,gTop)) << ");\n";
1196
stream << "\\path [kig grid] ("<< floor(qMin(0.0,gRight)) << ',' << floor(qMin(0.0,gBottom))
1197
<< ") grid (" << ceil(qMax(0.0,gRight)) << ',' << ceil(qMax(0.0,gBottom)) << ");\n";
1198
stream << "\\path [kig grid] ("<< floor(qMin(0.0,gLeft)) << ',' << floor(qMin(0.0,gBottom))
1199
<< ") grid (" << ceil(qMax(0.0,gLeft)) << ',' << ceil(qMax(0.0,gBottom)) << ");\n";
1203
if (gBottom < 0 && gTop > 0)
1205
stream << "\\path [kig axes] (" << gLeft << ",0) -- (" << gRight << ",0);\n";
1207
if (gLeft < 0 && gRight > 0)
1209
stream << "\\path [kig axes] (0," << gBottom <<") -- (0," << gTop << ");\n";
1212
for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
1213
i != os.end(); ++i )
1215
visitor.visit( *i );
1218
stream << "\\end{tikzpicture}\n";
1221
stream << "\\end{document}\n";
1225
else if (format == LatexExporterOptions::Asymptote)
1227
const double bottom = w.showingRect().bottom();
1228
const double left = w.showingRect().left();
1229
const double height = w.showingRect().height();
1230
const double width = w.showingRect().width();
1234
// The header if we embed into latex
1235
stream << "\\documentclass[a4paper,10pt]{article}\n";
1236
stream << "\\usepackage{asymptote}\n";
1238
stream << "\\pagestyle{empty}";
1240
stream << "\\begin{document}\n";
1243
stream << "\\begin{asy}[width=\\the\\linewidth]\n";
1245
stream << "import math;\n";
1246
stream << "import graph;\n";
1248
stream << "real textboxmargin = 2mm;\n";
1255
// vertical lines...
1256
double startingpoint = startingpoint = static_cast<double>( KDE_TRUNC( left ) );
1257
for ( double i = startingpoint; i < left+width; ++i )
1259
stream << "draw((" << i << "," << bottom << ")--(" << i << "," << bottom+height << "),gray);\n";
1261
// horizontal lines...
1262
startingpoint = static_cast<double>( KDE_TRUNC( bottom ) );
1263
for ( double i = startingpoint; i < bottom+height; ++i )
1265
stream << "draw((" << left << "," << i << ")--(" << left+width << "," << i << "),gray);\n";
1272
stream << "draw(("<<left<<",0)--("<<left+width<<",0), black, Arrow);\n";
1273
stream << "draw((0,"<<bottom<<")--(0,"<<bottom+height<<"), black, Arrow);\n";
1276
// Visit all the objects
1277
AsyExporterImpVisitor visitor( stream, w );
1279
for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
1281
visitor.visit( *i );
1284
// extra frame for clipping
1285
stream << "path frame = ("<<left<<","<<bottom<<")--("
1286
<<left<<","<<bottom+height<<")--("
1287
<<left+width<<","<<bottom+height<<")--("
1288
<<left+width<<","<<bottom<<")--cycle;\n";
1292
stream << "draw(frame, black);\n";
1294
stream << "clip(frame);\n";
1296
stream << "\\end{asy}\n";
1298
// The file footer in case we embed into latex
1301
stream << "\\end{document}\n";
1305
// And close the output file