~vaifrax/inkscape/bugfix170049

« back to all changes in this revision

Viewing changes to src/extension/internal/latex-pstricks.cpp

  • Committer: mental
  • Date: 2006-01-16 02:36:01 UTC
  • Revision ID: mental@users.sourceforge.net-20060116023601-wkr0h7edl5veyudq
moving trunk for module inkscape

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define __SP_LATEX_C__
 
2
 
 
3
/*
 
4
 * LaTeX Printing
 
5
 *
 
6
 * Author:
 
7
 *  Michael Forbes <miforbes@mbhs.edu>
 
8
 *
 
9
 * Copyright (C) 2004 Authors
 
10
 * 
 
11
 * Released under GNU GPL, read the file 'COPYING' for more information
 
12
 */
 
13
 
 
14
#ifdef HAVE_CONFIG_H
 
15
# include "config.h"
 
16
#endif
 
17
 
 
18
 
 
19
#include <signal.h>
 
20
#include <errno.h>
 
21
 
 
22
#include "libnr/n-art-bpath.h"
 
23
#include "sp-item.h"
 
24
 
 
25
 
 
26
#include "style.h"
 
27
 
 
28
#include "latex-pstricks.h"
 
29
 
 
30
#include <unit-constants.h>
 
31
 
 
32
#include "extension/system.h"
 
33
#include "extension/print.h"
 
34
 
 
35
#include "io/sys.h"
 
36
 
 
37
namespace Inkscape {
 
38
namespace Extension {
 
39
namespace Internal {
 
40
 
 
41
PrintLatex::PrintLatex (void): _stream(NULL)
 
42
{
 
43
}
 
44
 
 
45
PrintLatex::~PrintLatex (void)
 
46
{
 
47
    if (_stream) fclose(_stream);
 
48
 
 
49
    /* restore default signal handling for SIGPIPE */
 
50
#if !defined(_WIN32) && !defined(__WIN32__)
 
51
    (void) signal(SIGPIPE, SIG_DFL);
 
52
#endif
 
53
        return;
 
54
}
 
55
 
 
56
unsigned int
 
57
PrintLatex::setup (Inkscape::Extension::Print *mod)
 
58
{
 
59
    return TRUE;
 
60
}
 
61
 
 
62
unsigned int
 
63
PrintLatex::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
 
64
{
 
65
    Inkscape::SVGOStringStream os;
 
66
    int res;
 
67
    FILE *osf, *osp;
 
68
    const gchar * fn;
 
69
 
 
70
    fn = mod->get_param_string("destination");
 
71
 
 
72
    osf = NULL;
 
73
    osp = NULL;
 
74
 
 
75
    gsize bytesRead = 0;
 
76
    gsize bytesWritten = 0;
 
77
    GError* error = NULL;
 
78
    gchar* local_fn = g_filename_from_utf8( fn,
 
79
                                            -1,  &bytesRead,  &bytesWritten, &error);
 
80
    fn = local_fn;
 
81
 
 
82
    /* TODO: Replace the below fprintf's with something that does the right thing whether in
 
83
     * gui or batch mode (e.g. --print=blah).  Consider throwing an exception: currently one of
 
84
     * the callers (sp_print_document_to_file, "ret = mod->begin(doc)") wrongly ignores the
 
85
     * return code.
 
86
     */
 
87
    if (fn != NULL) {
 
88
        while (isspace(*fn)) fn += 1;
 
89
        Inkscape::IO::dump_fopen_call(fn, "K");
 
90
        osf = Inkscape::IO::fopen_utf8name(fn, "w+");
 
91
        if (!osf) {
 
92
            fprintf(stderr, "inkscape: fopen(%s): %s\n",
 
93
                    fn, strerror(errno));
 
94
            return 0;
 
95
        }
 
96
        _stream = osf;
 
97
    }
 
98
 
 
99
    g_free(local_fn);
 
100
 
 
101
    if (_stream) {
 
102
        /* fixme: this is kinda icky */
 
103
#if !defined(_WIN32) && !defined(__WIN32__)
 
104
        (void) signal(SIGPIPE, SIG_IGN);
 
105
#endif
 
106
    }
 
107
 
 
108
    res = fprintf(_stream, "%%LaTeX with PSTricks extensions\n");
 
109
    /* flush this to test output stream as early as possible */
 
110
    if (fflush(_stream)) {
 
111
        /*g_print("caught error in sp_module_print_plain_begin\n");*/
 
112
        if (ferror(_stream)) {
 
113
            g_print("Error %d on output stream: %s\n", errno,
 
114
                    g_strerror(errno));
 
115
        }
 
116
        g_print("Printing failed\n");
 
117
        /* fixme: should use pclose() for pipes */
 
118
        fclose(_stream);
 
119
        _stream = NULL;
 
120
        fflush(stdout);
 
121
        return 0;
 
122
    }
 
123
 
 
124
    // width and height in pt
 
125
    _width = sp_document_width(doc) * PT_PER_PX;
 
126
    _height = sp_document_height(doc) * PT_PER_PX;
 
127
 
 
128
    NRRect d;
 
129
    bool   pageLandscape;
 
130
    // printf("Page Bounding Box: %s\n", pageBoundingBox ? "TRUE" : "FALSE");
 
131
/*    if (pageBoundingBox) {
 
132
       d.x0 = d.y0 = 0;
 
133
        d.x1 = ceil(_width);
 
134
        d.y1 = ceil(_height);
 
135
    } else */{ // no bounding boxes for now
 
136
        SPItem* doc_item = SP_ITEM(sp_document_root(doc));
 
137
        sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE);
 
138
        // convert from px to pt
 
139
        d.x0 *= PT_PER_PX;
 
140
        d.x1 *= PT_PER_PX;
 
141
        d.y0 *= PT_PER_PX;
 
142
        d.y1 *= PT_PER_PX;
 
143
    }
 
144
 
 
145
 
 
146
    if (res >= 0) {
 
147
 
 
148
        os << "%%Creator: " << PACKAGE_STRING << "\n";
 
149
        os << "%%Please note this file requires PSTricks extensions\n";
 
150
 
 
151
        // 2004 Dec 10, BFC:
 
152
        // The point of the following code is (1) to do the thing that's expected by users
 
153
        // who have done File>New>A4_landscape or ...letter_landscape (i.e., rotate
 
154
        // the output), while (2) not messing up users who simply want their output wider
 
155
        // than it is tall (e.g., small figures for inclusion in LaTeX).
 
156
        // The original patch by WQ only had the w>h condition.
 
157
        {
 
158
             double w = (d.x1 - d.x0); // width and height of bounding box, in pt
 
159
             double h = (d.y1 - d.y0);
 
160
             pageLandscape = (
 
161
                 (w > 0. && h > 0.) // empty documents fail this sanity check, have w<0, h<0
 
162
                 && (w > h)   // implies, but does not prove, the user wanted landscape
 
163
                 && (w > 600) // approximate maximum printable width of an A4
 
164
             )
 
165
             ? true : false;
 
166
        }
 
167
 
 
168
        if (pageLandscape) {
 
169
            os << "\\rotate{90}\n";
 
170
        }
 
171
 
 
172
        os << "\\psset{xunit=.5pt,yunit=.5pt,runit=.5pt}\n";
 
173
        // from now on we can output px, but they will be treated as pt
 
174
    
 
175
        os << "\\begin{pspicture}(" << sp_document_width(doc) << "," << sp_document_height(doc) << ")\n";
 
176
    }
 
177
 
 
178
    return fprintf(_stream, "%s", os.str().c_str());
 
179
}
 
180
 
 
181
unsigned int
 
182
PrintLatex::finish (Inkscape::Extension::Print *mod)
 
183
{
 
184
    int res;
 
185
 
 
186
    if (!_stream) return 0;
 
187
 
 
188
    res = fprintf(_stream, "\\end{pspicture}\n");
 
189
 
 
190
    /* Flush stream to be sure. */
 
191
    (void) fflush(_stream);
 
192
 
 
193
    fclose(_stream);
 
194
    _stream = NULL;
 
195
    return 0;
 
196
}
 
197
 
 
198
unsigned int PrintLatex::comment (Inkscape::Extension::Print * module,
 
199
                                  const char * comment)
 
200
{
 
201
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
 
202
 
 
203
    return fprintf(_stream, "%%! %s\n",comment);
 
204
}
 
205
 
 
206
unsigned int
 
207
PrintLatex::fill(Inkscape::Extension::Print *mod,
 
208
                 NRBPath const *bpath, NRMatrix const *transform, SPStyle const *style,
 
209
                 NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
 
210
{
 
211
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
 
212
 
 
213
    if (style->fill.type == SP_PAINT_TYPE_COLOR) {
 
214
        Inkscape::SVGOStringStream os;
 
215
        float rgb[3];
 
216
 
 
217
        sp_color_get_rgb_floatv(&style->fill.value.color, rgb);
 
218
        os << "{\n\\newrgbcolor{curcolor}{" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "}\n";
 
219
 
 
220
        os << "\\pscustom[fillstyle=solid,fillcolor=curcolor]\n{\n";
 
221
 
 
222
        print_bpath(os, bpath->path, transform);
 
223
 
 
224
        os << "}\n}\n";
 
225
 
 
226
        fprintf(_stream, "%s", os.str().c_str());
 
227
    }        
 
228
 
 
229
    return 0;
 
230
}
 
231
 
 
232
unsigned int
 
233
PrintLatex::stroke (Inkscape::Extension::Print *mod, const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,
 
234
                              const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)
 
235
{
 
236
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
 
237
 
 
238
    if (style->stroke.type == SP_PAINT_TYPE_COLOR) {
 
239
        Inkscape::SVGOStringStream os;
 
240
        float rgb[3];
 
241
 
 
242
        sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
 
243
        os << "{\n\\newrgbcolor{curcolor}{" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "}\n";
 
244
 
 
245
        os << "\\pscustom[linewidth=" << style->stroke_width.computed<< ",linecolor=curcolor";
 
246
 
 
247
        if (style->stroke_dasharray_set &&
 
248
                style->stroke_dash.n_dash &&
 
249
                style->stroke_dash.dash) {
 
250
            int i;
 
251
            os << ",linestyle=dashed,dash=";
 
252
            for (i = 0; i < style->stroke_dash.n_dash; i++) {
 
253
                if ((i)) {
 
254
                    os << " ";
 
255
                }
 
256
                os << style->stroke_dash.dash[i];
 
257
            }
 
258
        }
 
259
 
 
260
        os <<"]\n{\n";
 
261
 
 
262
        print_bpath(os, bpath->path, transform);
 
263
 
 
264
        os << "}\n}\n";
 
265
 
 
266
        fprintf(_stream, "%s", os.str().c_str());
 
267
    }
 
268
 
 
269
    return 0;
 
270
}
 
271
 
 
272
void
 
273
PrintLatex::print_bpath(SVGOStringStream &os, const NArtBpath *bp, const NRMatrix *transform)
 
274
{
 
275
    unsigned int closed;
 
276
    NR::Matrix tf=*transform;
 
277
 
 
278
 
 
279
    os << "\\newpath\n";
 
280
    closed = FALSE;
 
281
    while (bp->code != NR_END) {
 
282
        using NR::X;
 
283
        using NR::Y;
 
284
        NR::Point const p1(bp->c(1) * tf);
 
285
        NR::Point const p2(bp->c(2) * tf);
 
286
        NR::Point const p3(bp->c(3) * tf);
 
287
        double const x1 = p1[X], y1 = p1[Y];
 
288
        double const x2 = p2[X], y2 = p2[Y];
 
289
        double const x3 = p3[X], y3 = p3[Y];
 
290
        
 
291
        switch (bp->code) {
 
292
            case NR_MOVETO:
 
293
                if (closed) {
 
294
                    os << "\\closepath\n";
 
295
                }
 
296
                closed = TRUE;
 
297
                os << "\\moveto(" << x3 << "," << y3 << ")\n";
 
298
                break;
 
299
            case NR_MOVETO_OPEN:
 
300
                if (closed) {
 
301
                    os << "\\closepath\n";
 
302
                }
 
303
                closed = FALSE;
 
304
                os << "\\moveto(" << x3 << "," << y3 << ")\n";
 
305
                break;
 
306
            case NR_LINETO:
 
307
                os << "\\lineto(" << x3 << "," << y3 << ")\n";
 
308
                break;
 
309
            case NR_CURVETO:
 
310
                os << "\\curveto(" << x1 << "," << y1 << ")("
 
311
                   << x2 << "," << y2 << ")("
 
312
                   << x3 << "," << y3 << ")\n";
 
313
                break;
 
314
            default:
 
315
                break;
 
316
        }
 
317
        bp += 1;
 
318
    }
 
319
    if (closed) {
 
320
        os << "\\closepath\n";
 
321
    }
 
322
}
 
323
 
 
324
bool
 
325
PrintLatex::textToPath(Inkscape::Extension::Print * ext)
 
326
{
 
327
    return ext->get_param_bool("textToPath");
 
328
}
 
329
 
 
330
void
 
331
PrintLatex::init (void)
 
332
{
 
333
        Inkscape::Extension::Extension * ext;
 
334
        
 
335
        /* SVG in */
 
336
    ext = Inkscape::Extension::build_from_mem(
 
337
                "<inkscape-extension>\n"
 
338
                        "<name>LaTeX Print</name>\n"
 
339
                        "<id>" SP_MODULE_KEY_PRINT_LATEX "</id>\n"
 
340
                        "<param name=\"destination\" type=\"string\"></param>\n"
 
341
                        "<param name=\"textToPath\" type=\"boolean\">TRUE</param>\n"
 
342
                        "<print/>\n"
 
343
                "</inkscape-extension>", new PrintLatex());
 
344
 
 
345
        return;
 
346
}
 
347
 
 
348
}  /* namespace Internal */
 
349
}  /* namespace Extension */
 
350
}  /* namespace Inkscape */
 
351
 
 
352
/*
 
353
  Local Variables:
 
354
  mode:c++
 
355
  c-file-style:"stroustrup"
 
356
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
357
  indent-tabs-mode:nil
 
358
  fill-column:99
 
359
  End:
 
360
*/
 
361
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
 
362