~ubuntu-branches/ubuntu/oneiric/kig/oneiric

« back to all changes in this revision

Viewing changes to filters/latexexporter.cc

  • Committer: Bazaar Package Importer
  • Author(s): Harald Sitter
  • Date: 2011-07-10 11:57:38 UTC
  • Revision ID: james.westby@ubuntu.com-20110710115738-gdjnn1kctr49lmy9
Tags: upstream-4.6.90+repack
ImportĀ upstreamĀ versionĀ 4.6.90+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C)  2004  Pino Toscano <toscano.pino@tiscali.it>
 
2
// Copyright (C)  2010,2011 Raoul Bourquin (asymptote exporter part)
 
3
 
 
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.
 
8
 
 
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.
 
13
 
 
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
 
17
// 02110-1301, USA.
 
18
 
 
19
#include "latexexporter.h"
 
20
#include "asyexporterimpvisitor.h"
 
21
#include "latexexporteroptions.h"
 
22
 
 
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"
 
43
 
 
44
#include <math.h>
 
45
#include <algorithm>
 
46
 
 
47
#include <qcheckbox.h>
 
48
#include <qcolor.h>
 
49
#include <qfile.h>
 
50
#include <qtextstream.h>
 
51
 
 
52
#include <klocale.h>
 
53
#include <kmessagebox.h>
 
54
 
 
55
#include <config-kig.h>
 
56
 
 
57
#ifdef HAVE_TRUNC
 
58
#define KDE_TRUNC(a)    trunc(a)
 
59
#else
 
60
#define KDE_TRUNC(a)    rint(a)
 
61
#endif
 
62
 
 
63
struct ColorMap {
 
64
    QColor color;
 
65
    QString name;
 
66
};
 
67
 
 
68
LatexExporter::~LatexExporter()
 
69
{
 
70
}
 
71
 
 
72
QString LatexExporter::exportToStatement() const
 
73
{
 
74
    return i18n( "Export to &Latex..." );
 
75
}
 
76
 
 
77
QString LatexExporter::menuEntryName() const
 
78
{
 
79
    return i18n( "&Latex..." );
 
80
}
 
81
 
 
82
QString LatexExporter::menuIcon() const
 
83
{
 
84
    return "text-x-tex";
 
85
}
 
86
 
 
87
class PSTricksExportImpVisitor
 
88
            : public ObjectImpVisitor
 
89
{
 
90
    QTextStream& mstream;
 
91
    ObjectHolder* mcurobj;
 
92
    const KigWidget& mw;
 
93
    Rect msr;
 
94
    std::vector<ColorMap> mcolors;
 
95
    QString mcurcolorid;
 
96
public:
 
97
    void visit( ObjectHolder* obj );
 
98
    void mapColor( const QColor& color );
 
99
 
 
100
    PSTricksExportImpVisitor( QTextStream& s, const KigWidget& w )
 
101
            : mstream( s ), mw( w ), msr( mw.showingRect() )
 
102
    {
 
103
    }
 
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 );
 
121
 
 
122
    double unit;
 
123
 
 
124
private:
 
125
    /**
 
126
     * Converts Kig coords to pstrick coord system and sends them to stream
 
127
     * using the format: (xcoord,ycoord)
 
128
     */
 
129
    void emitCoord( const Coordinate& c );
 
130
    /**
 
131
     * Draws a line (segment) or a vector if vector is true.
 
132
     */
 
133
    void emitLine( const Coordinate& a, const Coordinate& b, const int width,
 
134
                   const Qt::PenStyle s, bool vector = false );
 
135
    /**
 
136
     * Sends a new line character ( \n ) to stream.
 
137
     */
 
138
    void newLine();
 
139
    /**
 
140
     * Searches if a color is already mapped into mcolors, and returns its
 
141
     * index or -1 if not found.
 
142
     */
 
143
    int findColor( const QColor& c );
 
144
    /**
 
145
     * Use to convert a dimension "on the screen" to a dimension wrt.
 
146
     * Kig coordinate system.
 
147
     */
 
148
    double dimRealToCoord( int dim );
 
149
    /**
 
150
     * Converts a pen style into latex style string.
 
151
     */
 
152
    QString writeStyle( Qt::PenStyle style );
 
153
    /**
 
154
     * Plots a generic curve though its points calc'ed with getPoint.
 
155
     */
 
156
    void plotGenericCurve( const CurveImp* imp );
 
157
};
 
158
 
 
159
void PSTricksExportImpVisitor::emitCoord( const Coordinate& c )
 
160
{
 
161
    mstream << "(" << c.x - msr.left() << "," << c.y - msr.bottom() << ")";
 
162
}
 
163
 
 
164
void PSTricksExportImpVisitor::emitLine( const Coordinate& a, const Coordinate& b,
 
165
                                      const int width, const Qt::PenStyle s,
 
166
                                      bool vector )
 
167
{
 
168
    mstream << "\\psline[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0
 
169
    << "," << writeStyle( s );
 
170
    if ( vector )
 
171
        mstream << ",arrowscale=3,arrowinset=1.3";
 
172
    mstream << "]";
 
173
    if ( vector )
 
174
        mstream << "{->}";
 
175
    emitCoord( a );
 
176
    emitCoord( b );
 
177
    newLine();
 
178
}
 
179
 
 
180
void PSTricksExportImpVisitor::newLine()
 
181
{
 
182
    mstream << "\n";
 
183
}
 
184
 
 
185
int PSTricksExportImpVisitor::findColor( const QColor& c )
 
186
{
 
187
    for ( uint i = 0; i < mcolors.size(); ++i )
 
188
    {
 
189
        if ( c == mcolors[i].color )
 
190
            return i;
 
191
    }
 
192
    return -1;
 
193
}
 
194
 
 
195
void PSTricksExportImpVisitor::mapColor( const QColor& color )
 
196
{
 
197
    if ( findColor( color ) == -1 )
 
198
    {
 
199
        ColorMap newcolor;
 
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";
 
208
    }
 
209
}
 
210
 
 
211
double PSTricksExportImpVisitor::dimRealToCoord( int dim )
 
212
{
 
213
    QRect qr( 0, 0, dim, dim );
 
214
    Rect r = mw.screenInfo().fromScreen( qr );
 
215
    return fabs( r.width() );
 
216
}
 
217
 
 
218
QString PSTricksExportImpVisitor::writeStyle( Qt::PenStyle style )
 
219
{
 
220
    QString ret( "linestyle=" );
 
221
    if ( style == Qt::DashLine )
 
222
        ret += "dashed";
 
223
    else if ( style == Qt::DotLine )
 
224
        ret += "dotted,dotsep=2pt";
 
225
    else
 
226
        ret += "solid";
 
227
    return ret;
 
228
}
 
229
 
 
230
void PSTricksExportImpVisitor::plotGenericCurve( const CurveImp* imp )
 
231
{
 
232
    int width = mcurobj->drawer()->width();
 
233
    if ( width == -1 ) width = 1;
 
234
 
 
235
    QString prefix = QString( "\\pscurve[linecolor=%1,linewidth=%2,%3]" )
 
236
                     .arg( mcurcolorid )
 
237
                     .arg( width / 100.0 )
 
238
                     .arg( writeStyle( mcurobj->drawer()->style() ) );
 
239
 
 
240
    std::vector< std::vector< Coordinate > > coordlist;
 
241
    coordlist.push_back( std::vector< Coordinate >() );
 
242
    uint curid = 0;
 
243
 
 
244
    Coordinate c;
 
245
    Coordinate prev = Coordinate::invalidCoord();
 
246
    for ( double i = 0.0; i <= 1.0; i += 0.005 )
 
247
    {
 
248
        c = imp->getPoint( i, mw.document() );
 
249
        if ( !c.valid() )
 
250
        {
 
251
            if ( coordlist[curid].size() > 0 )
 
252
            {
 
253
                coordlist.push_back( std::vector< Coordinate >() );
 
254
                ++curid;
 
255
                prev = Coordinate::invalidCoord();
 
256
            }
 
257
            continue;
 
258
        }
 
259
        if ( ! ( ( fabs( c.x ) <= 1000 ) && ( fabs( c.y ) <= 1000 ) ) )
 
260
            continue;
 
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 ) )
 
264
        {
 
265
            coordlist.push_back( std::vector< Coordinate >() );
 
266
            ++curid;
 
267
        }
 
268
        coordlist[curid].push_back( c );
 
269
        prev = c;
 
270
    }
 
271
    // special case for ellipse
 
272
    if ( const ConicImp* conic = dynamic_cast< const ConicImp* >( imp ) )
 
273
    {
 
274
        // if ellipse, close its path
 
275
        if ( conic->conicType() == 1 && coordlist.size() == 1 && coordlist[0].size() > 1 )
 
276
        {
 
277
            coordlist[0].push_back( coordlist[0][0] );
 
278
        }
 
279
    }
 
280
    for ( uint i = 0; i < coordlist.size(); ++i )
 
281
    {
 
282
        uint s = coordlist[i].size();
 
283
        // there's no point in draw curves empty or with only one point
 
284
        if ( s <= 1 )
 
285
            continue;
 
286
 
 
287
        mstream << prefix;
 
288
        for ( uint j = 0; j < s; ++j )
 
289
            emitCoord( coordlist[i][j] );
 
290
        newLine();
 
291
    }
 
292
}
 
293
 
 
294
void PSTricksExportImpVisitor::visit( ObjectHolder* obj )
 
295
{
 
296
    if ( ! obj->drawer()->shown() )
 
297
        return;
 
298
    const int id = findColor( obj->drawer()->color() );
 
299
    if ( id == -1 )
 
300
        return;
 
301
    mcurcolorid = mcolors[id].name;
 
302
    mcurobj = obj;
 
303
    obj->imp()->visit( this );
 
304
}
 
305
 
 
306
void PSTricksExportImpVisitor::visit( const LineImp* imp )
 
307
{
 
308
    Coordinate a = imp->data().a;
 
309
    Coordinate b = imp->data().b;
 
310
    calcBorderPoints( a, b, msr );
 
311
 
 
312
    int width = mcurobj->drawer()->width();
 
313
    if ( width == -1 ) width = 1;
 
314
 
 
315
    emitLine( a, b, width, mcurobj->drawer()->style() );
 
316
}
 
317
 
 
318
void PSTricksExportImpVisitor::visit( const PointImp* imp )
 
319
{
 
320
    int width = mcurobj->drawer()->width();
 
321
    if ( width == -1 ) width = 5;
 
322
    width /= 5;
 
323
 
 
324
    mstream << "\\psdots[linecolor=" << mcurcolorid
 
325
    << ",dotscale=" << width << ",dotstyle=";
 
326
    const int ps = mcurobj->drawer()->pointStyle();
 
327
    QString pss( "*,fillstyle=solid,fillcolor=" + mcurcolorid );
 
328
    if ( ps == 1 )
 
329
        pss = "o,fillstyle=none";
 
330
    else if ( ps == 2 )
 
331
        pss = "square*,fillstyle=solid,fillcolor=" + mcurcolorid;
 
332
    else if ( ps == 3 )
 
333
        pss = "square,fillstyle=none";
 
334
    else if ( ps == 4 )
 
335
        pss = "+,dotangle=45";
 
336
    mstream << pss << "]";
 
337
    emitCoord( imp->coordinate() );
 
338
    newLine();
 
339
}
 
340
 
 
341
void PSTricksExportImpVisitor::visit( const TextImp* imp )
 
342
{
 
343
    // FIXME: support multiline texts...
 
344
    mstream << "\\rput[tl]";
 
345
    emitCoord( imp->coordinate() );
 
346
    newLine();
 
347
    mstream << "{";
 
348
    newLine();
 
349
    if ( imp->hasFrame() )
 
350
    {
 
351
        mstream << "  \\psframebox[linecolor=c5c2c5,linewidth=0.01"
 
352
        << ",fillstyle=solid,fillcolor=ffffde]"
 
353
        << "{" << imp->text() << "}";
 
354
    }
 
355
    else
 
356
    {
 
357
        mstream << imp->text();
 
358
    }
 
359
    newLine();
 
360
    mstream << "}";
 
361
    newLine();
 
362
}
 
363
 
 
364
void PSTricksExportImpVisitor::visit( const AngleImp* imp )
 
365
{
 
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;
 
378
 
 
379
    mstream << "\\psarc[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0
 
380
    << "," << writeStyle( mcurobj->drawer()->style() ) << ",arrowscale=3,arrowinset=0]{->}";
 
381
    emitCoord( center );
 
382
    mstream << "{" <<  radius << "}{" << startangle << "}{" << endangle << "}";
 
383
    newLine();
 
384
}
 
385
 
 
386
void PSTricksExportImpVisitor::visit( const VectorImp* imp )
 
387
{
 
388
    Coordinate a = imp->data().a;
 
389
    Coordinate b = imp->data().b;
 
390
 
 
391
    int width = mcurobj->drawer()->width();
 
392
    if ( width == -1 ) width = 1;
 
393
 
 
394
    emitLine( a, b, width, mcurobj->drawer()->style(), true );
 
395
}
 
396
 
 
397
void PSTricksExportImpVisitor::visit( const LocusImp* imp )
 
398
{
 
399
    plotGenericCurve( imp );
 
400
}
 
401
 
 
402
void PSTricksExportImpVisitor::visit( const CircleImp* imp )
 
403
{
 
404
    int width = mcurobj->drawer()->width();
 
405
    if ( width == -1 ) width = 1;
 
406
 
 
407
    mstream << "\\pscircle[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0
 
408
    << "," << writeStyle( mcurobj->drawer()->style() ) << "]";
 
409
    emitCoord( imp->center() );
 
410
    mstream << "{" << imp->radius() * unit << "}";
 
411
    newLine();
 
412
}
 
413
 
 
414
void PSTricksExportImpVisitor::visit( const ConicImp* imp )
 
415
{
 
416
    plotGenericCurve( imp );
 
417
}
 
418
 
 
419
void PSTricksExportImpVisitor::visit( const CubicImp* )
 
420
{
 
421
    // FIXME: cubic are not drawn correctly with plotGenericCurve
 
422
//  plotGenericCurve( imp );
 
423
}
 
424
 
 
425
void PSTricksExportImpVisitor::visit( const SegmentImp* imp )
 
426
{
 
427
    Coordinate a = imp->data().a;
 
428
    Coordinate b = imp->data().b;
 
429
 
 
430
    int width = mcurobj->drawer()->width();
 
431
    if ( width == -1 ) width = 1;
 
432
 
 
433
    emitLine( a, b, width, mcurobj->drawer()->style() );
 
434
}
 
435
 
 
436
void PSTricksExportImpVisitor::visit( const RayImp* imp )
 
437
{
 
438
    Coordinate a = imp->data().a;
 
439
    Coordinate b = imp->data().b;
 
440
    calcRayBorderPoints( a, b, msr );
 
441
 
 
442
    int width = mcurobj->drawer()->width();
 
443
    if ( width == -1 ) width = 1;
 
444
 
 
445
    emitLine( a, b, width, mcurobj->drawer()->style() );
 
446
}
 
447
 
 
448
void PSTricksExportImpVisitor::visit( const ArcImp* imp )
 
449
{
 
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;
 
462
 
 
463
    mstream << "\\psarc[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0
 
464
    << "," << writeStyle( mcurobj->drawer()->style() ) << "]";
 
465
    emitCoord( center );
 
466
    mstream << "{" <<  radius << "}{" << startangle << "}{" << endangle << "}";
 
467
    newLine();
 
468
}
 
469
 
 
470
void PSTricksExportImpVisitor::visit( const FilledPolygonImp* imp )
 
471
{
 
472
    int width = mcurobj->drawer()->width();
 
473
    if ( width == -1 ) width = 1;
 
474
 
 
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]";
 
479
 
 
480
    std::vector<Coordinate> pts = imp->points();
 
481
    for ( uint i = 0; i < pts.size(); i++ )
 
482
    {
 
483
        emitCoord( pts[i] );
 
484
    }
 
485
    newLine();
 
486
}
 
487
 
 
488
void PSTricksExportImpVisitor::visit(const ClosedPolygonalImp* imp)
 
489
{
 
490
    int width = mcurobj->drawer()->width();
 
491
    if ( width == -1 ) width = 1;
 
492
 
 
493
    mstream << "\\pspolygon[linecolor=" << mcurcolorid << ",linewidth=0"
 
494
    << "," << writeStyle( mcurobj->drawer()->style() ) << ']';
 
495
 
 
496
    std::vector<Coordinate> pts = imp->points();
 
497
    for ( uint i = 0; i < pts.size(); i++ )
 
498
    {
 
499
        emitCoord( pts[i] );
 
500
    }
 
501
    newLine();
 
502
}
 
503
 
 
504
void PSTricksExportImpVisitor::visit(const OpenPolygonalImp* imp)
 
505
{
 
506
    int width = mcurobj->drawer()->width();
 
507
    if ( width == -1 ) width = 1;
 
508
 
 
509
    mstream << "\\psline[linecolor=" << mcurcolorid << ",linewidth=0"
 
510
    << "," << writeStyle( mcurobj->drawer()->style() ) << ']';
 
511
 
 
512
    std::vector<Coordinate> pts = imp->points();
 
513
    for ( uint i = 0; i < pts.size(); i++ )
 
514
    {
 
515
        emitCoord( pts[i] );
 
516
    }
 
517
    newLine();
 
518
}
 
519
 
 
520
// TODO: Just a quick fix, improve when reviewing PSTricks exporter
 
521
void PSTricksExportImpVisitor::visit(const BezierImp* imp)
 
522
{
 
523
  plotGenericCurve(imp);
 
524
}
 
525
 
 
526
// TODO: Just a quick fix, improve when reviewing PSTricks exporter
 
527
void PSTricksExportImpVisitor::visit(const RationalBezierImp* imp)
 
528
{
 
529
  plotGenericCurve(imp);
 
530
}
 
531
 
 
532
 
 
533
class TikZExportImpVisitor
 
534
            : public ObjectImpVisitor
 
535
{
 
536
    QTextStream& mstream;
 
537
    ObjectHolder* mcurobj;
 
538
    const KigWidget& mw;
 
539
    Rect msr;
 
540
    std::vector<ColorMap> mcolors;
 
541
    QString mcurcolorid;
 
542
public:
 
543
    void visit( ObjectHolder* obj );
 
544
    void mapColor( const QColor& color );
 
545
 
 
546
    TikZExportImpVisitor( QTextStream& s, const KigWidget& w )
 
547
            : mstream( s ), mw( w ), msr( mw.showingRect() )
 
548
    {
 
549
    }
 
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);
 
567
 
 
568
    double unit;
 
569
 
 
570
private:
 
571
    /**
 
572
     * Converts Kig coords to pstrick coord system and sends them to stream
 
573
     * using the format: (xcoord,ycoord)
 
574
     */
 
575
    void emitCoord( const Coordinate& c );
 
576
    /**
 
577
     * Draws a line (segment) or a vector if vector is true.
 
578
     */
 
579
    void emitLine( const Coordinate& a, const Coordinate& b, const int width,
 
580
                   const Qt::PenStyle s, bool vector = false );
 
581
    /**
 
582
     * Sends a new line character ( \n ) to stream.
 
583
     */
 
584
    void newLine();
 
585
    /**
 
586
     * Searches if a color is already mapped into mcolors, and returns its
 
587
     * index or -1 if not found.
 
588
     */
 
589
    int findColor( const QColor& c );
 
590
    /**
 
591
     * Use to convert a dimension "on the screen" to a dimension wrt.
 
592
     * Kig coordinate system.
 
593
     */
 
594
    double dimRealToCoord( int dim );
 
595
    /**
 
596
     * Converts a pen style into latex style string.
 
597
     */
 
598
    QString writeStyle( Qt::PenStyle style );
 
599
    /**
 
600
     * Plots a generic curve though its points calc'ed with getPoint.
 
601
     */
 
602
    void plotGenericCurve( const CurveImp* imp );
 
603
};
 
604
 
 
605
void TikZExportImpVisitor::emitCoord( const Coordinate& c )
 
606
{
 
607
    mstream << '(' << c.x << ',' << c.y << ')';
 
608
}
 
609
 
 
610
void TikZExportImpVisitor::emitLine( const Coordinate& a, const Coordinate& b,
 
611
                                     const int width, const Qt::PenStyle s,
 
612
                                     bool vector )
 
613
{
 
614
    if (vector)
 
615
    {
 
616
        mstream << "\\draw[->,color=" << mcurcolorid << ",line width=" << width <<']';
 
617
    }
 
618
    else
 
619
    {
 
620
        mstream << "\\draw[color=" << mcurcolorid << ",line width=" << width << ']';
 
621
    }
 
622
    mstream << ' ';
 
623
    emitCoord(a);
 
624
    mstream << " -- ";
 
625
    emitCoord(b);
 
626
    newLine();
 
627
}
 
628
 
 
629
void TikZExportImpVisitor::newLine()
 
630
{
 
631
    mstream << ";\n";
 
632
    mstream.flush();
 
633
}
 
634
 
 
635
int TikZExportImpVisitor::findColor( const QColor& c )
 
636
{
 
637
    for ( uint i = 0; i < mcolors.size(); ++i )
 
638
    {
 
639
        if ( c == mcolors[i].color )
 
640
            return i;
 
641
    }
 
642
    return -1;
 
643
}
 
644
 
 
645
void TikZExportImpVisitor::mapColor( const QColor& color )
 
646
{
 
647
    if ( findColor( color ) == -1 )
 
648
    {
 
649
        ColorMap newcolor;
 
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";
 
656
    }
 
657
}
 
658
 
 
659
QString TikZExportImpVisitor::writeStyle( Qt::PenStyle style )
 
660
{
 
661
    QString ret;
 
662
    /*
 
663
    ret += "line style=";
 
664
    if ( style == Qt::DashLine )
 
665
    ret += "dashed";
 
666
    else if ( style == Qt::DotLine )
 
667
    ret += "dotted,dotsep=2pt";
 
668
    else
 
669
    ret += "solid";
 
670
    */
 
671
    return ret;
 
672
}
 
673
 
 
674
void TikZExportImpVisitor::plotGenericCurve( const CurveImp* imp )
 
675
{
 
676
    int width = mcurobj->drawer()->width();
 
677
    if ( width == -1 ) width = 1;
 
678
 
 
679
    std::vector< std::vector< Coordinate > > coordlist;
 
680
    coordlist.push_back( std::vector< Coordinate >() );
 
681
    uint curid = 0;
 
682
 
 
683
    Coordinate c;
 
684
    Coordinate prev = Coordinate::invalidCoord();
 
685
    for ( double i = 0.0; i <= 1.0; i += 0.005 )
 
686
    {
 
687
        c = imp->getPoint( i, mw.document() );
 
688
        if ( !c.valid() )
 
689
        {
 
690
            if ( coordlist[curid].size() > 0 )
 
691
            {
 
692
                coordlist.push_back( std::vector< Coordinate >() );
 
693
                ++curid;
 
694
                prev = Coordinate::invalidCoord();
 
695
            }
 
696
            continue;
 
697
        }
 
698
        if ( ! ( ( fabs( c.x ) <= 1000 ) && ( fabs( c.y ) <= 1000 ) ) )
 
699
            continue;
 
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 ) )
 
703
        {
 
704
            coordlist.push_back( std::vector< Coordinate >() );
 
705
            ++curid;
 
706
        }
 
707
        coordlist[curid].push_back( c );
 
708
        prev = c;
 
709
    }
 
710
 
 
711
    for ( uint i = 0; i < coordlist.size(); ++i )
 
712
    {
 
713
        uint s = coordlist[i].size();
 
714
        // there's no point in draw curves empty or with only one point
 
715
        if ( s <= 1 )
 
716
            continue;
 
717
 
 
718
        mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << ']';
 
719
        for ( uint j = 0; j < s; ++j )
 
720
        {
 
721
            emitCoord( coordlist[i][j] );
 
722
            if (j < s - 1)
 
723
            {
 
724
                mstream << " -- ";
 
725
            }
 
726
        }
 
727
        newLine();
 
728
    }
 
729
 
 
730
}
 
731
 
 
732
void TikZExportImpVisitor::visit( ObjectHolder* obj )
 
733
{
 
734
    mstream << "%% " << obj->imp()->type()->translatedName();
 
735
    newLine();
 
736
    if ( ! obj->drawer()->shown() )
 
737
        return;
 
738
    const int id = findColor( obj->drawer()->color() );
 
739
    if ( id == -1 )
 
740
        return;
 
741
    mcurcolorid = mcolors[id].name;
 
742
    mcurobj = obj;
 
743
    obj->imp()->visit( this );
 
744
}
 
745
 
 
746
void TikZExportImpVisitor::visit( const LineImp* imp )
 
747
{
 
748
    Coordinate a = imp->data().a;
 
749
    Coordinate b = imp->data().b;
 
750
    calcBorderPoints( a, b, msr );
 
751
 
 
752
    int width = mcurobj->drawer()->width();
 
753
    if ( width == -1 ) width = 1;
 
754
 
 
755
    emitLine( a, b, width, mcurobj->drawer()->style() );
 
756
}
 
757
 
 
758
void TikZExportImpVisitor::visit( const PointImp* imp )
 
759
{
 
760
    int width = mcurobj->drawer()->width();
 
761
    if ( width == -1 ) width = 1;
 
762
 
 
763
    mstream << "\\path [fill=" << mcurcolorid << "] ";
 
764
    emitCoord (imp->coordinate());
 
765
    mstream << " circle (" << width << "pt)";
 
766
    newLine();
 
767
}
 
768
 
 
769
void TikZExportImpVisitor::visit( const TextImp* imp )
 
770
{
 
771
    mstream << "\\node ";
 
772
    if (imp->hasFrame())
 
773
    {
 
774
        mstream << "[rectangle,draw] ";
 
775
    }
 
776
    mstream << "at ";
 
777
    emitCoord(imp->coordinate());
 
778
    mstream << " {" << imp->text() << "}";
 
779
    newLine();
 
780
}
 
781
 
 
782
void TikZExportImpVisitor::visit( const AngleImp* imp )
 
783
{
 
784
    int width = mcurobj->drawer()->width();
 
785
    if ( width == -1 ) width = 1;
 
786
 
 
787
    double start = Goniometry::convert( imp->startAngle(), Goniometry::Rad, Goniometry::Deg );
 
788
    double end = Goniometry::convert( imp->startAngle() + imp->angle(), Goniometry::Rad, Goniometry::Deg );
 
789
    double radius = 0.5;
 
790
    mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << ']';
 
791
    emitCoord(imp->point());
 
792
    mstream << " +(" << start << ':' << radius << ')';
 
793
    mstream << " arc (" << start << ':' << end <<  ':' << radius << ')';
 
794
    newLine();
 
795
}
 
796
 
 
797
void TikZExportImpVisitor::visit( const VectorImp* imp )
 
798
{
 
799
    Coordinate a = imp->data().a;
 
800
    Coordinate b = imp->data().b;
 
801
 
 
802
    int width = mcurobj->drawer()->width();
 
803
    if ( width == -1 ) width = 1;
 
804
 
 
805
    emitLine( a, b, width, mcurobj->drawer()->style(), true );
 
806
}
 
807
 
 
808
void TikZExportImpVisitor::visit( const LocusImp* imp )
 
809
{
 
810
    plotGenericCurve( imp );
 
811
}
 
812
 
 
813
void TikZExportImpVisitor::visit( const CircleImp* imp )
 
814
{
 
815
    int width = mcurobj->drawer()->width();
 
816
    if ( width == -1 ) width = 1;
 
817
 
 
818
    mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
 
819
    emitCoord( imp->center() );
 
820
    mstream << " circle (" << imp->radius() << ')';
 
821
    newLine();
 
822
}
 
823
 
 
824
void TikZExportImpVisitor::visit( const ConicImp* imp )
 
825
{
 
826
    plotGenericCurve(imp);
 
827
}
 
828
 
 
829
void TikZExportImpVisitor::visit( const CubicImp* imp )
 
830
{
 
831
    plotGenericCurve(imp);
 
832
}
 
833
 
 
834
void TikZExportImpVisitor::visit( const SegmentImp* imp )
 
835
{
 
836
    Coordinate a = imp->data().a;
 
837
    Coordinate b = imp->data().b;
 
838
 
 
839
    int width = mcurobj->drawer()->width();
 
840
    if ( width == -1 ) width = 1;
 
841
 
 
842
    emitLine( a, b, width, mcurobj->drawer()->style() );
 
843
}
 
844
 
 
845
void TikZExportImpVisitor::visit( const RayImp* imp )
 
846
{
 
847
    Coordinate a = imp->data().a;
 
848
    Coordinate b = imp->data().b;
 
849
    calcRayBorderPoints( a, b, msr );
 
850
 
 
851
    int width = mcurobj->drawer()->width();
 
852
    if ( width == -1 ) width = 1;
 
853
 
 
854
    emitLine( a, b, width, mcurobj->drawer()->style() );
 
855
}
 
856
 
 
857
void TikZExportImpVisitor::visit( const ArcImp* imp )
 
858
{
 
859
    int width = mcurobj->drawer()->width();
 
860
    if ( width == -1 ) width = 1;
 
861
 
 
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 << ")";
 
869
    newLine();
 
870
}
 
871
 
 
872
void TikZExportImpVisitor::visit( const FilledPolygonImp* imp )
 
873
{
 
874
    int width = mcurobj->drawer()->width();
 
875
    if ( width == -1 ) width = 1;
 
876
 
 
877
    mstream << "\\path [fill,color=" << mcurcolorid << ",line width=" << width << "] ";
 
878
 
 
879
    std::vector<Coordinate> pts = imp->points();
 
880
    for ( uint i = 0; i < pts.size(); i++ )
 
881
    {
 
882
        emitCoord( pts[i] );
 
883
        mstream << "  --  ";
 
884
    }
 
885
    mstream << "cycle";
 
886
    newLine();
 
887
}
 
888
 
 
889
 
 
890
void TikZExportImpVisitor::visit ( const ClosedPolygonalImp* imp )
 
891
{
 
892
    int width = mcurobj->drawer()->width();
 
893
    if ( width == -1 ) width = 1;
 
894
 
 
895
    mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
 
896
 
 
897
    std::vector<Coordinate> pts = imp->points();
 
898
    for ( uint i = 0; i < pts.size(); i++ )
 
899
    {
 
900
        emitCoord( pts[i] );
 
901
        mstream << "  --  ";
 
902
    }
 
903
    mstream << "cycle";
 
904
    newLine();
 
905
}
 
906
 
 
907
void TikZExportImpVisitor::visit ( const OpenPolygonalImp* imp )
 
908
{
 
909
    int width = mcurobj->drawer()->width();
 
910
    if ( width == -1 ) width = 1;
 
911
 
 
912
    mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
 
913
 
 
914
    std::vector<Coordinate> pts = imp->points();
 
915
    for ( uint i = 0; i < pts.size(); i++ )
 
916
    {
 
917
        emitCoord( pts[i] );
 
918
        if (i < pts.size() - 1)
 
919
        {
 
920
            mstream << "  --  ";
 
921
        }
 
922
    }
 
923
    newLine();
 
924
}
 
925
 
 
926
void TikZExportImpVisitor::visit(const BezierImp* imp)
 
927
{
 
928
    int width = mcurobj->drawer()->width();
 
929
    if ( width == -1 ) width = 1;
 
930
 
 
931
    std::vector<Coordinate> pts = imp->points();
 
932
    switch (pts.size())
 
933
    {
 
934
    case 3:
 
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 ";
 
942
        mstream << "($";
 
943
        emitCoord(pts.at(0));
 
944
        mstream << "+2/3*";
 
945
        emitCoord(pts.at(1));
 
946
        mstream << "-2/3*";
 
947
        emitCoord(pts.at(0));
 
948
        mstream << "$)";
 
949
        mstream << " and ";
 
950
        mstream << "($";
 
951
        emitCoord(pts.at(0));
 
952
        mstream << "+2/3*";
 
953
        emitCoord(pts.at(1));
 
954
        mstream << "-2/3*";
 
955
        emitCoord(pts.at(0));
 
956
        mstream << "+1/3*";
 
957
        emitCoord(pts.at(2));
 
958
        mstream << "-1/3*";
 
959
        emitCoord(pts.at(0));
 
960
        mstream << "$)";
 
961
        mstream << " .. ";
 
962
        emitCoord(pts.at(2));
 
963
        newLine();
 
964
        break;
 
965
    case 4:
 
966
        mstream << "\\path [draw,color=" << mcurcolorid << ",line width=" << width << "] ";
 
967
        emitCoord(pts.front());
 
968
        mstream << ".. controls ";
 
969
        emitCoord(pts.at(1));
 
970
        mstream << " and ";
 
971
        emitCoord(pts.at(2));
 
972
        mstream << " .. ";
 
973
        emitCoord(pts.back());
 
974
        newLine();
 
975
        break;
 
976
    default:
 
977
        plotGenericCurve(imp);
 
978
        break;
 
979
    }
 
980
}
 
981
 
 
982
// TODO: Just a quick fix, improve when reviewing TikZ exporter
 
983
void TikZExportImpVisitor::visit(const RationalBezierImp* imp)
 
984
{
 
985
  plotGenericCurve(imp);
 
986
}
 
987
 
 
988
 
 
989
void LatexExporter::run( const KigPart& doc, KigWidget& w )
 
990
{
 
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 );
 
997
 
 
998
    opts->setGrid( doc.document().grid() );
 
999
    opts->setAxes( doc.document().axes() );
 
1000
    opts->setExtraFrame( false );
 
1001
 
 
1002
    KConfigGroup cg = KGlobal::config()->group("Latex Exporter");
 
1003
 
 
1004
    int fmt = cg.readEntry<int>("OutputFormat", LatexExporterOptions::PSTricks);
 
1005
    if (fmt > -1 && fmt < LatexExporterOptions::FormatCount)
 
1006
    {
 
1007
        opts->setFormat((LatexExporterOptions::LatexOutputFormat)fmt);
 
1008
    }
 
1009
    opts->setStandalone(cg.readEntry("Standalone", true));
 
1010
 
 
1011
    if ( !kfd->exec() )
 
1012
        return;
 
1013
 
 
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();
 
1020
 
 
1021
    delete opts;
 
1022
    delete kfd;
 
1023
 
 
1024
    cg.writeEntry("OutputFormat", (int)format);
 
1025
    cg.writeEntry("Standalone", standalone);
 
1026
 
 
1027
    QFile file( file_name );
 
1028
    if ( ! file.open( QIODevice::WriteOnly ) )
 
1029
    {
 
1030
        KMessageBox::sorry( &w, i18n( "The file \"%1\" could not be opened. Please "
 
1031
                                      "check if the file permissions are set correctly." ,
 
1032
                                      file_name ) );
 
1033
        return;
 
1034
    };
 
1035
 
 
1036
    QTextStream stream( &file );
 
1037
    std::vector<ObjectHolder*> os = doc.document().objects();
 
1038
 
 
1039
    if (format == LatexExporterOptions::PSTricks)
 
1040
    {
 
1041
        if (standalone)
 
1042
        {
 
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";
 
1049
        }
 
1050
 
 
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();
 
1055
 
 
1056
        /*
 
1057
          // TODO: calculating aspect ratio...
 
1058
          if ( 297 / 210 >= height / width )
 
1059
          {
 
1060
 
 
1061
          }
 
1062
        */
 
1063
        const double tmpwidth = 15.0;
 
1064
        const double xunit = tmpwidth / width;
 
1065
        const double yunit = xunit;
 
1066
 
 
1067
        stream << "\\begin{pspicture*}(0,0)(" << tmpwidth << "," << yunit * height << ")\n";
 
1068
        stream << "\\psset{xunit=" << xunit << "}\n";
 
1069
        stream << "\\psset{yunit=" << yunit << "}\n";
 
1070
 
 
1071
        PSTricksExportImpVisitor visitor( stream, w );
 
1072
        visitor.unit = xunit;
 
1073
 
 
1074
        for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
 
1075
                i != os.end(); ++i )
 
1076
        {
 
1077
            if ( ! ( *i )->shown() ) continue;
 
1078
            visitor.mapColor( ( *i )->drawer()->color() );
 
1079
        };
 
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
 
1084
 
 
1085
        // extra frame
 
1086
        if ( showframe )
 
1087
        {
 
1088
            stream << "\\psframe[linecolor=black,linewidth=0.02]"
 
1089
            << "(0,0)"
 
1090
            << "(" << width << "," << height << ")"
 
1091
            << "\n";
 
1092
        }
 
1093
 
 
1094
        // grid
 
1095
        if ( showgrid )
 
1096
        {
 
1097
            // vertical lines...
 
1098
            double startingpoint = - left - 1 + static_cast<int>( KDE_TRUNC( left ) );
 
1099
            for ( double i = startingpoint; i < width; ++i )
 
1100
            {
 
1101
                stream << "\\psline[linecolor=c0c0c0,linewidth=0.01,linestyle=dashed]"
 
1102
                << "(" << i << ",0)"
 
1103
                << "(" << i << "," << height << ")"
 
1104
                << "\n";
 
1105
            }
 
1106
 
 
1107
            // horizontal lines...
 
1108
            startingpoint = - bottom - 1 + static_cast<int>( KDE_TRUNC( bottom ) );
 
1109
            for ( double i = startingpoint; i < height; ++i )
 
1110
            {
 
1111
                stream << "\\psline[linecolor=c0c0c0,linewidth=0.01,linestyle=dashed]"
 
1112
                << "(0," << i << ")"
 
1113
                << "(" << width << "," << i << ")"
 
1114
                << "\n";
 
1115
            }
 
1116
        }
 
1117
 
 
1118
        // axes
 
1119
        if ( showaxes )
 
1120
        {
 
1121
            stream << "\\psaxes[linecolor=a0a0a4,linewidth=0.03,ticks=none,arrowinset=0]{->}"
 
1122
            << "(" << -left << "," << -bottom << ")"
 
1123
            << "(0,0)"
 
1124
            << "(" << width << "," << height << ")"
 
1125
            << "\n";
 
1126
        }
 
1127
 
 
1128
        for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
 
1129
                i != os.end(); ++i )
 
1130
        {
 
1131
            visitor.visit( *i );
 
1132
        };
 
1133
 
 
1134
        stream << "\\end{pspicture*}\n";
 
1135
        if (standalone)
 
1136
        {
 
1137
            stream << "\\end{document}\n";
 
1138
        }
 
1139
    }
 
1140
    else if (format == LatexExporterOptions::TikZ)
 
1141
    {
 
1142
      if (standalone)
 
1143
      {
 
1144
            stream << "\\documentclass[a4paper]{minimal}\n";
 
1145
        //  stream << "\\usepackage[latin1]{inputenc}\n";
 
1146
            stream << "\\usepackage{tikz}\n";
 
1147
            stream << "\\usetikzlibrary{calc}\n";
 
1148
            if (showgrid)
 
1149
            {
 
1150
              stream << "\\tikzset{kig grid/.style=draw,help lines}\n";
 
1151
            }
 
1152
            if (showaxes)
 
1153
            {
 
1154
              stream << "\\tikzset{kig axes/.style=draw,help lines,->}\n";
 
1155
            }
 
1156
            if (showframe)
 
1157
            {
 
1158
              stream << "\\tikzset{kig frame/.style=draw,black}\n";
 
1159
            }
 
1160
            stream << "\\author{Kig " << KIGVERSION << "}\n";
 
1161
            stream << "\\begin{document}\n";
 
1162
      }
 
1163
      TikZExportImpVisitor visitor( stream, w );
 
1164
 
 
1165
        Rect frameRect = w.showingRect();
 
1166
 
 
1167
        for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
 
1168
                i != os.end(); ++i )
 
1169
        {
 
1170
            if ( ! ( *i )->shown() ) continue;
 
1171
            visitor.mapColor( ( *i )->drawer()->color() );
 
1172
        }
 
1173
 
 
1174
        double size = qMax(frameRect.height(),frameRect.width());
 
1175
        double scale = (size == 0) ? 1 : 10/size;
 
1176
 
 
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();
 
1183
 
 
1184
        stream << "\\clip (" << gLeft << ',' << gBottom << ") rectangle (" << gRight << ',' << gTop << ");\n";
 
1185
 
 
1186
        if (showframe)
 
1187
        {
 
1188
            stream << "\\path [kig frame] (" << gLeft << ',' << gBottom << ") rectangle (" << gRight << ',' << gTop << ");\n";
 
1189
        }
 
1190
        if (showgrid)
 
1191
        {
 
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";
 
1200
        }
 
1201
        if (showaxes)
 
1202
        {
 
1203
            if (gBottom < 0 && gTop > 0)
 
1204
            {
 
1205
                stream << "\\path [kig axes] (" << gLeft << ",0) -- (" << gRight << ",0);\n";
 
1206
            }
 
1207
            if (gLeft < 0 && gRight > 0)
 
1208
            {
 
1209
                stream << "\\path [kig axes] (0," << gBottom <<") -- (0," << gTop << ");\n";
 
1210
            }
 
1211
        }
 
1212
        for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
 
1213
                i != os.end(); ++i )
 
1214
        {
 
1215
            visitor.visit( *i );
 
1216
        };
 
1217
 
 
1218
        stream << "\\end{tikzpicture}\n";
 
1219
        if (standalone)
 
1220
        {
 
1221
          stream << "\\end{document}\n";
 
1222
        }
 
1223
 
 
1224
    }
 
1225
    else if (format == LatexExporterOptions::Asymptote)
 
1226
    {
 
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();
 
1231
 
 
1232
        if (standalone)
 
1233
        {
 
1234
            // The header if we embed into latex
 
1235
            stream << "\\documentclass[a4paper,10pt]{article}\n";
 
1236
            stream << "\\usepackage{asymptote}\n";
 
1237
            stream << "\n";
 
1238
            stream << "\\pagestyle{empty}";
 
1239
            stream << "\n";
 
1240
            stream << "\\begin{document}\n";
 
1241
        }
 
1242
 
 
1243
        stream << "\\begin{asy}[width=\\the\\linewidth]\n";
 
1244
        stream << "\n";
 
1245
        stream << "import math;\n";
 
1246
        stream << "import graph;\n";
 
1247
        stream << "\n";
 
1248
        stream << "real textboxmargin = 2mm;\n";
 
1249
        stream << "\n";
 
1250
 
 
1251
        // grid
 
1252
        if ( showgrid )
 
1253
        {
 
1254
          // TODO: Polar grid
 
1255
          // vertical lines...
 
1256
          double startingpoint = startingpoint = static_cast<double>( KDE_TRUNC( left ) );
 
1257
          for ( double i = startingpoint; i < left+width; ++i )
 
1258
          {
 
1259
            stream << "draw((" << i << "," << bottom << ")--(" << i << "," << bottom+height << "),gray);\n";
 
1260
          }
 
1261
          // horizontal lines...
 
1262
          startingpoint = static_cast<double>( KDE_TRUNC( bottom ) );
 
1263
          for ( double i = startingpoint; i < bottom+height; ++i )
 
1264
          {
 
1265
            stream << "draw((" << left << "," << i << ")--(" << left+width << "," << i << "),gray);\n";
 
1266
          }
 
1267
        }
 
1268
 
 
1269
    // axes
 
1270
    if ( showaxes )
 
1271
    {
 
1272
      stream << "draw(("<<left<<",0)--("<<left+width<<",0), black, Arrow);\n";
 
1273
      stream << "draw((0,"<<bottom<<")--(0,"<<bottom+height<<"), black, Arrow);\n";
 
1274
    }
 
1275
 
 
1276
        // Visit all the objects
 
1277
        AsyExporterImpVisitor visitor( stream, w );
 
1278
 
 
1279
        for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
 
1280
        {
 
1281
            visitor.visit( *i );
 
1282
        }
 
1283
 
 
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";
 
1289
 
 
1290
        if ( showframe )
 
1291
        {
 
1292
            stream << "draw(frame, black);\n";
 
1293
        }
 
1294
        stream << "clip(frame);\n";
 
1295
        stream << "\n";
 
1296
        stream << "\\end{asy}\n";
 
1297
 
 
1298
        // The file footer in case we embed into latex
 
1299
        if ( standalone )
 
1300
        {
 
1301
            stream << "\\end{document}\n";
 
1302
        }
 
1303
    }
 
1304
 
 
1305
    // And close the output file
 
1306
    file.close();
 
1307
}