~ubuntu-branches/debian/experimental/inkscape/experimental

« back to all changes in this revision

Viewing changes to src/extension/internal/pdf.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define __SP_PDF_C__
2
 
 
3
 
/** \file
4
 
 * PDF printing.
5
 
 */
6
 
/*
7
 
 * Authors:
8
 
 *   Lauris Kaplinski <lauris@kaplinski.com>
9
 
 *   bulia byak <buliabyak@users.sf.net>
10
 
 *   Ulf Erikson <ulferikson@users.sf.net>
11
 
 *
12
 
 * Basic printing code, EXCEPT image and
13
 
 * ascii85 filter is in public domain
14
 
 *
15
 
 * Image printing and Ascii85 filter:
16
 
 *
17
 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
18
 
 * Copyright (C) 1997-98 Peter Kirchgessner
19
 
 * George White <aa056@chebucto.ns.ca>
20
 
 * Austin Donnelly <austin@gimp.org>
21
 
 *
22
 
 * Licensed under GNU GPL
23
 
 */
24
 
 
25
 
/* Plain Print */
26
 
 
27
 
#ifdef HAVE_CONFIG_H
28
 
# include "config.h"
29
 
#endif
30
 
 
31
 
#include <signal.h>
32
 
#include <errno.h>
33
 
 
34
 
#include <glib/gmem.h>
35
 
#include <libnr/n-art-bpath.h>
36
 
#include <libnr/nr-point-matrix-ops.h>
37
 
 
38
 
#include <gtk/gtkstock.h>
39
 
#include <gtk/gtkvbox.h>
40
 
#include <gtk/gtkframe.h>
41
 
#include <gtk/gtkradiobutton.h>
42
 
#include <gtk/gtkcombo.h>
43
 
#include <gtk/gtklabel.h>
44
 
#include <gtk/gtkentry.h>
45
 
#include <gtk/gtktooltips.h>
46
 
 
47
 
#include <glibmm/i18n.h>
48
 
#include "display/nr-arena-item.h"
49
 
#include "display/canvas-bpath.h"
50
 
#include "sp-item.h"
51
 
#include "style.h"
52
 
#include "sp-linear-gradient.h"
53
 
#include "sp-radial-gradient.h"
54
 
 
55
 
#include "libnrtype/font-instance.h"
56
 
#include "libnrtype/font-style-to-pos.h"
57
 
 
58
 
#include <unit-constants.h>
59
 
 
60
 
#include "pdf.h"
61
 
#include "extension/system.h"
62
 
#include "extension/print.h"
63
 
 
64
 
#include "io/sys.h"
65
 
 
66
 
#include "pdf-mini.h"
67
 
 
68
 
namespace Inkscape {
69
 
namespace Extension {
70
 
namespace Internal {
71
 
 
72
 
PrintPDF::PrintPDF() :
73
 
    _stream(NULL),
74
 
    _dpi(72),
75
 
    _bitmap(false)
76
 
{
77
 
}
78
 
 
79
 
PrintPDF::~PrintPDF(void)
80
 
{
81
 
    /* fixme: should really use pclose for popen'd streams */
82
 
    if (_stream) fclose(_stream);
83
 
 
84
 
    /* restore default signal handling for SIGPIPE */
85
 
#if !defined(_WIN32) && !defined(__WIN32__)
86
 
    (void) signal(SIGPIPE, SIG_DFL);
87
 
#endif
88
 
 
89
 
    return;
90
 
}
91
 
 
92
 
unsigned int
93
 
PrintPDF::setup(Inkscape::Extension::Print * mod)
94
 
{
95
 
    static gchar const *const pdr[] = {"72", "75", "100", "144", "150", "200", "300", "360", "600", "1200", "2400", NULL};
96
 
 
97
 
#ifdef TED
98
 
    Inkscape::XML::Node *repr = ((SPModule *) mod)->repr;
99
 
#endif
100
 
 
101
 
    unsigned int ret = FALSE;
102
 
 
103
 
    /* Create dialog */
104
 
    GtkTooltips *tt = gtk_tooltips_new();
105
 
    g_object_ref((GObject *) tt);
106
 
    gtk_object_sink((GtkObject *) tt);
107
 
 
108
 
    GtkWidget *dlg = gtk_dialog_new_with_buttons(_("Print Destination"),
109
 
//            SP_DT_WIDGET(SP_ACTIVE_DESKTOP)->window,
110
 
            NULL,
111
 
            (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT),
112
 
            GTK_STOCK_CANCEL,
113
 
            GTK_RESPONSE_CANCEL,
114
 
            GTK_STOCK_PRINT,
115
 
            GTK_RESPONSE_OK,
116
 
            NULL);
117
 
 
118
 
    gtk_dialog_set_default_response(GTK_DIALOG(dlg), GTK_RESPONSE_OK);
119
 
 
120
 
    GtkWidget *vbox = GTK_DIALOG(dlg)->vbox;
121
 
    gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
122
 
    /* Print properties frame */
123
 
    GtkWidget *f = gtk_frame_new(_("Print properties"));
124
 
    gtk_box_pack_start(GTK_BOX(vbox), f, FALSE, FALSE, 4);
125
 
    GtkWidget *vb = gtk_vbox_new(FALSE, 4);
126
 
    gtk_container_add(GTK_CONTAINER(f), vb);
127
 
    gtk_container_set_border_width(GTK_CONTAINER(vb), 4);
128
 
    /* Print type */
129
 
    bool const p2bm = mod->get_param_bool("bitmap");
130
 
    GtkWidget *rb = gtk_radio_button_new_with_label(NULL, _("Print using PDF operators"));
131
 
    gtk_tooltips_set_tip((GtkTooltips *) tt, rb,
132
 
                         _("Use PDF vector operators. The resulting image is usually smaller "
133
 
                           "in file size and can be arbitrarily scaled, but "
134
 
                           "patterns will be lost."), NULL);
135
 
    if (!p2bm) gtk_toggle_button_set_active((GtkToggleButton *) rb, TRUE);
136
 
    gtk_box_pack_start(GTK_BOX(vb), rb, FALSE, FALSE, 0);
137
 
    rb = gtk_radio_button_new_with_label(gtk_radio_button_get_group((GtkRadioButton *) rb), _("Print as bitmap"));
138
 
    gtk_tooltips_set_tip((GtkTooltips *) tt, rb,
139
 
                         _("Print everything as bitmap. The resulting image is usually larger "
140
 
                           "in file size and cannot be arbitrarily scaled without quality loss, "
141
 
                           "but all objects will be rendered exactly as displayed."), NULL);
142
 
    if (p2bm) gtk_toggle_button_set_active((GtkToggleButton *) rb, TRUE);
143
 
    gtk_box_pack_start(GTK_BOX(vb), rb, FALSE, FALSE, 0);
144
 
    /* Resolution */
145
 
    GtkWidget *hb = gtk_hbox_new(FALSE, 4);
146
 
    gtk_box_pack_start(GTK_BOX(vb), hb, FALSE, FALSE, 0);
147
 
    GtkWidget *combo = gtk_combo_new();
148
 
    gtk_combo_set_value_in_list(GTK_COMBO(combo), FALSE, FALSE);
149
 
    gtk_combo_set_use_arrows(GTK_COMBO(combo), TRUE);
150
 
    gtk_combo_set_use_arrows_always(GTK_COMBO(combo), TRUE);
151
 
    gtk_widget_set_size_request(combo, 64, -1);
152
 
    gtk_tooltips_set_tip((GtkTooltips *) tt, GTK_COMBO(combo)->entry,
153
 
                         _("Preferred resolution (dots per inch) of bitmap"), NULL);
154
 
    /* Setup strings */
155
 
    GList *sl = NULL;
156
 
    for (unsigned i = 0; pdr[i] != NULL; i++) {
157
 
        sl = g_list_prepend(sl, (gpointer) pdr[i]);
158
 
    }
159
 
    sl = g_list_reverse(sl);
160
 
    gtk_combo_set_popdown_strings(GTK_COMBO(combo), sl);
161
 
    g_list_free(sl);
162
 
    if (1) {
163
 
        gchar const *val = mod->get_param_string("resolution");
164
 
        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), val);
165
 
    }
166
 
    gtk_box_pack_end(GTK_BOX(hb), combo, FALSE, FALSE, 0);
167
 
    GtkWidget *l = gtk_label_new(_("Resolution:"));
168
 
    gtk_box_pack_end(GTK_BOX(hb), l, FALSE, FALSE, 0);
169
 
 
170
 
    /* Print destination frame */
171
 
    f = gtk_frame_new(_("Print destination"));
172
 
    gtk_box_pack_start(GTK_BOX(vbox), f, FALSE, FALSE, 4);
173
 
    vb = gtk_vbox_new(FALSE, 4);
174
 
    gtk_container_add(GTK_CONTAINER(f), vb);
175
 
    gtk_container_set_border_width(GTK_CONTAINER(vb), 4);
176
 
 
177
 
    l = gtk_label_new(_("Printer name (as given by lpstat -p);\n"
178
 
                        "leave empty to use the system default printer.\n"
179
 
                        "Use '> filename' to print to file.\n"
180
 
                        "Use '| prog arg...' to pipe to a program."));
181
 
    gtk_box_pack_start(GTK_BOX(vb), l, FALSE, FALSE, 0);
182
 
 
183
 
    GtkWidget *e = gtk_entry_new();
184
 
    if (1) {
185
 
        gchar const *val = mod->get_param_string("destination");
186
 
        gtk_entry_set_text(GTK_ENTRY(e), ( val != NULL
187
 
                                           ? val
188
 
                                           : "" ));
189
 
    }
190
 
    gtk_box_pack_start(GTK_BOX(vb), e, FALSE, FALSE, 0);
191
 
 
192
 
    // pressing enter in the destination field is the same as clicking Print:
193
 
    gtk_entry_set_activates_default(GTK_ENTRY(e), TRUE);
194
 
 
195
 
    gtk_widget_show_all(vbox);
196
 
 
197
 
    int const response = gtk_dialog_run(GTK_DIALOG(dlg));
198
 
 
199
 
    g_object_unref((GObject *) tt);
200
 
 
201
 
    if (response == GTK_RESPONSE_OK) {
202
 
        gchar const *fn;
203
 
        char const *sstr;
204
 
 
205
 
        _bitmap = gtk_toggle_button_get_active((GtkToggleButton *) rb);
206
 
        sstr = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
207
 
        _dpi = (unsigned int) MAX((int)(atof(sstr)), 1);
208
 
        /* Arrgh, have to do something */
209
 
        fn = gtk_entry_get_text(GTK_ENTRY(e));
210
 
        /* skip leading whitespace, bug #1068483 */
211
 
        while (fn && *fn==' ') { fn++; }
212
 
        /* g_print("Printing to %s\n", fn); */
213
 
 
214
 
        mod->set_param_bool("bitmap", _bitmap);
215
 
        mod->set_param_string("resolution", (gchar *)sstr);
216
 
        mod->set_param_string("destination", (gchar *)fn);
217
 
        ret = TRUE;
218
 
    }
219
 
 
220
 
    gtk_widget_destroy(dlg);
221
 
 
222
 
    return ret;
223
 
}
224
 
 
225
 
unsigned int
226
 
PrintPDF::begin(Inkscape::Extension::Print *mod, SPDocument *doc)
227
 
{
228
 
    gboolean epsexport = false;
229
 
 
230
 
    _latin1_encoded_fonts.clear();
231
 
    _newlatin1font_proc_defined = false;
232
 
 
233
 
    FILE *osf = NULL;
234
 
    FILE *osp = NULL;
235
 
 
236
 
    gsize bytesRead = 0;
237
 
    gsize bytesWritten = 0;
238
 
    GError *error = NULL;
239
 
    gchar const *utf8_fn = mod->get_param_string("destination");
240
 
    gchar *local_fn = g_filename_from_utf8( utf8_fn,
241
 
                                            -1,  &bytesRead,  &bytesWritten, &error);
242
 
    gchar const *fn = local_fn;
243
 
 
244
 
    /* TODO: Replace the below fprintf's with something that does the right thing whether in
245
 
     * gui or batch mode (e.g. --print=blah).  Consider throwing an exception: currently one of
246
 
     * the callers (sp_print_document_to_file, "ret = mod->begin(doc)") wrongly ignores the
247
 
     * return code.
248
 
     */
249
 
    if (fn != NULL) {
250
 
        if (*fn == '|') {
251
 
            fn += 1;
252
 
            while (isspace(*fn)) fn += 1;
253
 
#ifndef WIN32
254
 
            osp = popen(fn, "wb");
255
 
#else
256
 
            osp = _popen(fn, "wb");
257
 
#endif
258
 
            if (!osp) {
259
 
                fprintf(stderr, "inkscape: popen(%s): %s\n",
260
 
                        fn, strerror(errno));
261
 
                return 0;
262
 
            }
263
 
            _stream = osp;
264
 
        } else if (*fn == '>') {
265
 
            fn += 1;
266
 
            epsexport = g_str_has_suffix(fn,".eps");
267
 
            while (isspace(*fn)) fn += 1;
268
 
            Inkscape::IO::dump_fopen_call(fn, "K");
269
 
            osf = Inkscape::IO::fopen_utf8name(fn, "wb+");
270
 
            if (!osf) {
271
 
                fprintf(stderr, "inkscape: fopen(%s): %s\n",
272
 
                        fn, strerror(errno));
273
 
                return 0;
274
 
            }
275
 
            _stream = osf;
276
 
        } else {
277
 
            /* put cwd stuff in here */
278
 
            gchar *qn = ( *fn
279
 
                          ? g_strdup_printf("lpr -P %s", fn)  /* FIXME: quote fn */
280
 
                          : g_strdup("lpr") );
281
 
#ifndef WIN32
282
 
            osp = popen(qn, "wb");
283
 
#else
284
 
            osp = _popen(qn, "wb");
285
 
#endif
286
 
            if (!osp) {
287
 
                fprintf(stderr, "inkscape: popen(%s): %s\n",
288
 
                        qn, strerror(errno));
289
 
                return 0;
290
 
            }
291
 
            g_free(qn);
292
 
            _stream = osp;
293
 
        }
294
 
    }
295
 
 
296
 
    g_free(local_fn);
297
 
 
298
 
    if (_stream) {
299
 
        /* fixme: this is kinda icky */
300
 
#if !defined(_WIN32) && !defined(__WIN32__)
301
 
        (void) signal(SIGPIPE, SIG_IGN);
302
 
#endif
303
 
    }
304
 
 
305
 
    pdf_file = new PdfFile(_stream);
306
 
    doc_info = pdf_file->begin_document(1.4);
307
 
    *doc_info << "  /Title(" << doc->name << ")\n";
308
 
    *doc_info << "  /Author(" << g_get_real_name()  << ")\n";
309
 
//    *doc_info << "  /Subject(" << "?" << ")\n";
310
 
//    *doc_info << "  /Keywords(" << "?" << ")\n";
311
 
    *doc_info << "  /Creator(" << "www.inkscape.org" << ")\n";
312
 
    *doc_info << "  /Producer(" << "Inkscape " << PACKAGE_STRING << ")\n";
313
 
        //the date should be in ISO/IEC 8824
314
 
        GDate date;
315
 
        GTimeVal ltime;
316
 
        glong time_hh, time_mm, time_ss;
317
 
#if GLIB_CHECK_VERSION(2,9,0)
318
 
        g_date_set_time_t (&date, time (NULL));
319
 
#else
320
 
        g_date_set_time(&date, time (NULL));
321
 
#endif
322
 
        gchar date_str[100], time_str[100];
323
 
        g_date_strftime(date_str, 99, "%Y%m%d", &date);
324
 
        g_get_current_time(&ltime);
325
 
        time_hh=(ltime.tv_sec/3600)%24;
326
 
        time_mm=(ltime.tv_sec/60)%60;
327
 
        time_ss=(ltime.tv_sec)%60;
328
 
        g_snprintf(time_str, 99, "%02ld%02ld%02ld", time_hh, time_mm, time_ss); 
329
 
        *doc_info << "  /CreationDate(D:" << date_str << time_str << "Z)\n";
330
 
//      *doc_info << "  /CreationDate(D:" << date_str << time_str << "OHH'mm')\n";
331
 
 
332
 
    /* flush this to test output stream as early as possible */
333
 
    if (fflush(_stream)) {
334
 
        /*g_print("caught error in sp_module_print_plain_begin\n");*/
335
 
        if (ferror(_stream)) {
336
 
            g_print("Error %d on output stream: %s\n", errno,
337
 
                    g_strerror(errno));
338
 
        }
339
 
        g_print("Printing failed\n");
340
 
        /* fixme: should use pclose() for pipes */
341
 
        fclose(_stream);
342
 
        _stream = NULL;
343
 
        fflush(stdout);
344
 
        return 0;
345
 
    }
346
 
 
347
 
    // width and height in pt
348
 
    _width = sp_document_width(doc) * PT_PER_PX;
349
 
    _height = sp_document_height(doc) * PT_PER_PX;
350
 
 
351
 
    NRRect d;
352
 
    bool   pageBoundingBox;
353
 
    pageBoundingBox = mod->get_param_bool("pageBoundingBox");
354
 
    // printf("Page Bounding Box: %s\n", pageBoundingBox ? "TRUE" : "FALSE");
355
 
    if (pageBoundingBox) {
356
 
        d.x0 = d.y0 = 0;
357
 
        d.x1 = ceil(_width);
358
 
        d.y1 = ceil(_height);
359
 
    } else {
360
 
        SPItem* doc_item = SP_ITEM(sp_document_root(doc));
361
 
        sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE);
362
 
        // convert from px to pt
363
 
        d.x0 *= PT_PER_PX;
364
 
        d.x1 *= PT_PER_PX;
365
 
        d.y0 *= PT_PER_PX;
366
 
        d.y1 *= PT_PER_PX;
367
 
    }
368
 
 
369
 
    page_stream = pdf_file->begin_page( (int) d.x0, (int) d.y0,
370
 
                                        (int) d.x1, (int) d.y1 );
371
 
 
372
 
    if (!_bitmap) {
373
 
        *page_stream << PT_PER_PX << " 0 0 "
374
 
                     << -PT_PER_PX << " 0 " << (int) ceil(_height)
375
 
                     << " cm\n";
376
 
        // from now on we can output px, but they will be treated as pt
377
 
    }
378
 
    
379
 
    return 1;
380
 
}
381
 
 
382
 
unsigned int
383
 
PrintPDF::finish(Inkscape::Extension::Print *mod)
384
 
{
385
 
    if (!_stream) return 0;
386
 
 
387
 
    if (_bitmap) {
388
 
        double const dots_per_pt = _dpi / PT_PER_IN;
389
 
 
390
 
        double const x0 = 0.0;
391
 
        double const y0 = 0.0;
392
 
        double const x1 = x0 + _width;
393
 
        double const y1 = y0 + _height;
394
 
 
395
 
        /* Bitmap width/height in bitmap dots. */
396
 
        int const width = (int) (_width * dots_per_pt + 0.5);
397
 
        int const height = (int) (_height * dots_per_pt + 0.5);
398
 
 
399
 
        NRMatrix affine;
400
 
        affine.c[0] = width / ((x1 - x0) * PX_PER_PT);
401
 
        affine.c[1] = 0.0;
402
 
        affine.c[2] = 0.0;
403
 
        affine.c[3] = height / ((y1 - y0) * PX_PER_PT);
404
 
        affine.c[4] = -affine.c[0] * x0;
405
 
        affine.c[5] = -affine.c[3] * y0;
406
 
 
407
 
        nr_arena_item_set_transform(mod->root, &affine);
408
 
 
409
 
        guchar *const px = g_new(guchar, 4 * width * 64);
410
 
 
411
 
        for (int y = 0; y < height; y += 64) {
412
 
            /* Set area of interest. */
413
 
            NRRectL bbox;
414
 
            bbox.x0 = 0;
415
 
            bbox.y0 = y;
416
 
            bbox.x1 = width;
417
 
            bbox.y1 = MIN(height, y + 64);
418
 
 
419
 
            /* Update to renderable state. */
420
 
            NRGC gc(NULL);
421
 
            nr_matrix_set_identity(&gc.transform);
422
 
            nr_arena_item_invoke_update(mod->root, &bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
423
 
            /* Render */
424
 
            /* This should take guchar* instead of unsigned char*) */
425
 
            NRPixBlock pb;
426
 
            nr_pixblock_setup_extern(&pb, NR_PIXBLOCK_MODE_R8G8B8A8N,
427
 
                                     bbox.x0, bbox.y0, bbox.x1, bbox.y1,
428
 
                                     (guchar*)px, 4 * width, FALSE, FALSE);
429
 
            memset(px, 0xff, 4 * width * 64);
430
 
            nr_arena_item_invoke_render(mod->root, &bbox, &pb, 0);
431
 
            /* Blitter goes here */
432
 
            NRMatrix imgt;
433
 
            imgt.c[0] = (bbox.x1 - bbox.x0) / dots_per_pt;
434
 
            imgt.c[1] = 0.0;
435
 
            imgt.c[2] = 0.0;
436
 
            imgt.c[3] = (bbox.y1 - bbox.y0) / dots_per_pt;
437
 
            imgt.c[4] = 0.0;
438
 
            imgt.c[5] = _height - y / dots_per_pt - (bbox.y1 - bbox.y0) / dots_per_pt;
439
 
 
440
 
            print_image(_stream, px, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0, 4 * width, &imgt);
441
 
        }
442
 
 
443
 
        g_free(px);
444
 
    }
445
 
 
446
 
    pdf_file->end_page(page_stream);
447
 
    pdf_file->end_document(doc_info);
448
 
 
449
 
    delete pdf_file;
450
 
 
451
 
    /* Flush stream to be sure. */
452
 
    (void) fflush(_stream);
453
 
 
454
 
    /* fixme: should really use pclose for popen'd streams */
455
 
    fclose(_stream);
456
 
    _stream = 0;
457
 
    _latin1_encoded_fonts.clear();
458
 
 
459
 
    return 0;
460
 
}
461
 
 
462
 
unsigned int
463
 
PrintPDF::bind(Inkscape::Extension::Print *mod, NRMatrix const *transform, float opacity)
464
 
{
465
 
    if (!_stream) return 0;  // XXX: fixme, returning -1 as unsigned.
466
 
    if (_bitmap) return 0;
467
 
 
468
 
    *page_stream << "q\n";
469
 
    *page_stream << transform->c[0] << " "
470
 
                 << transform->c[1] << " "
471
 
                 << transform->c[2] << " "
472
 
                 << transform->c[3] << " "
473
 
                 << transform->c[4] << " "
474
 
                 << transform->c[5] << " cm\n";
475
 
 
476
 
    return 1;
477
 
}
478
 
 
479
 
unsigned int
480
 
PrintPDF::release(Inkscape::Extension::Print *mod)
481
 
{
482
 
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
483
 
    if (_bitmap) return 0;
484
 
 
485
 
    *page_stream << "Q\n";
486
 
 
487
 
    return 1;
488
 
}
489
 
 
490
 
unsigned int
491
 
PrintPDF::comment(Inkscape::Extension::Print *mod, char const *comment)
492
 
{
493
 
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
494
 
    if (_bitmap) return 0;
495
 
 
496
 
    *page_stream << "% " << comment;
497
 
 
498
 
    return 1;
499
 
}
500
 
 
501
 
void
502
 
PrintPDF::print_fill_alpha(SVGOStringStream &/*os*/, SPStyle const *const style, NRRect const *pbox)
503
 
{
504
 
    g_return_if_fail( style->fill.type == SP_PAINT_TYPE_COLOR
505
 
                      || ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
506
 
                           && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) ) );
507
 
    
508
 
    if (style->fill.type == SP_PAINT_TYPE_COLOR) {
509
 
        float alpha = 1.0;
510
 
        
511
 
        if (style->opacity.set)
512
 
            alpha *= SP_SCALE24_TO_FLOAT(style->opacity.value);
513
 
        
514
 
        if (style->fill_opacity.set)
515
 
            alpha *= SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
516
 
 
517
 
        if (alpha != 1.0) {
518
 
            PdfObject *pdf_alpha = pdf_file->begin_resource(pdf_extgstate);
519
 
            *pdf_alpha << "<< /Type /ExtGState\n";
520
 
            *pdf_alpha << "   /ca " << alpha << "\n";
521
 
            *pdf_alpha << "   /AIS false\n";
522
 
            *pdf_alpha << ">>\n";
523
 
            
524
 
            *page_stream << pdf_alpha->get_name()
525
 
                         << " gs\n";
526
 
            
527
 
            pdf_file->end_resource(pdf_alpha);
528
 
        }
529
 
    } else {
530
 
        g_assert( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
531
 
                  && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) );
532
 
        
533
 
        if (SP_IS_LINEARGRADIENT (SP_STYLE_FILL_SERVER (style))) {
534
 
            
535
 
            SPLinearGradient *lg=SP_LINEARGRADIENT(SP_STYLE_FILL_SERVER (style));
536
 
            sp_gradient_ensure_vector(SP_GRADIENT(lg)); // when exporting from commandline, vector is not built
537
 
 
538
 
            NR::Point p1 (lg->x1.computed, lg->y1.computed);
539
 
            NR::Point p2 (lg->x2.computed, lg->y2.computed);
540
 
            if (pbox && SP_GRADIENT(lg)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
541
 
                // convert to userspace
542
 
                NR::Matrix bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
543
 
                p1 *= bbox2user;
544
 
                p2 *= bbox2user;
545
 
            }
546
 
            
547
 
            double alpha = 1.0;
548
 
            for (gint i = 0; unsigned(i) < lg->vector.stops.size(); i++) {
549
 
                alpha *= lg->vector.stops[i].opacity;
550
 
            }
551
 
            
552
 
            if (alpha != 1.0 || style->opacity.set) {
553
 
                PdfObject *pdf_gstate = pdf_file->begin_resource(pdf_extgstate);
554
 
                *pdf_gstate << "<< /Type /ExtGState\n";
555
 
                
556
 
                if (style->opacity.set) {
557
 
                    *pdf_gstate << "   /ca " << SP_SCALE24_TO_FLOAT(style->opacity.value) << "\n";
558
 
                    *pdf_gstate << "   /AIS false\n";
559
 
                }
560
 
                
561
 
                if (alpha != 1.0) {
562
 
                    PdfObject *pdf_alpha = pdf_file->begin_resource(pdf_shading);
563
 
                    PdfObject *pdf_smask = pdf_file->begin_resource(pdf_none);
564
 
                    PdfObject *pdf_xobj = pdf_file->begin_resource(pdf_none);
565
 
 
566
 
 
567
 
                    *pdf_gstate << "   /SMask " << pdf_smask->get_id() << " 0 R\n";
568
 
 
569
 
            
570
 
                    *pdf_alpha << "<<\n/ShadingType 2\n/ColorSpace /DeviceGray\n";
571
 
                    *pdf_alpha << "/Coords [" << p1[NR::X] << " " << p1[NR::Y] << " " << p2[NR::X] << " " << p2[NR::Y] <<"]\n";
572
 
                    *pdf_alpha << "/Extend [true true]\n";
573
 
                    *pdf_alpha << "/Domain [0 1]\n";
574
 
                    *pdf_alpha << "/Function <<\n/FunctionType 3\n/Functions\n[\n";
575
 
 
576
 
                    for (gint i = 0; unsigned(i) < lg->vector.stops.size() - 1; i++) {
577
 
                        *pdf_alpha << "<<\n/FunctionType 2\n/Domain [0 1]\n";
578
 
                        *pdf_alpha << "/C0 [" << lg->vector.stops[i].opacity << "]\n";
579
 
                        *pdf_alpha << "/C1 [" << lg->vector.stops[i+1].opacity << "]\n";
580
 
                        *pdf_alpha << "/N 1\n>>\n";
581
 
                    }
582
 
                    *pdf_alpha << "]\n/Domain [0 1]\n";
583
 
                    *pdf_alpha << "/Bounds [ ";
584
 
                    for (gint i=0;unsigned(i)<lg->vector.stops.size()-2;i++) {
585
 
                        *pdf_alpha << lg->vector.stops[i+1].offset <<" ";
586
 
                    }
587
 
                    *pdf_alpha << "]\n";
588
 
                    *pdf_alpha << "/Encode [ ";
589
 
                    for (gint i=0;unsigned(i)<lg->vector.stops.size()-1;i++) {
590
 
                        *pdf_alpha << "0 1 ";
591
 
                    }
592
 
                    *pdf_alpha << "]\n";
593
 
                    *pdf_alpha << ">>\n>>\n";
594
 
 
595
 
                    
596
 
                    *pdf_smask << "<< /Type /Mask\n";
597
 
                    *pdf_smask << "   /S /Alpha\n";
598
 
                    *pdf_smask << "   /BC [0.0]\n";
599
 
                    *pdf_smask << "   /G " << pdf_xobj->get_id() << " 0 R\n";
600
 
                    *pdf_smask << ">>\n";
601
 
 
602
 
                    
603
 
                    *pdf_xobj << "<< /Type /XObject\n";
604
 
                    *pdf_xobj << "   /Subtype /Form\n";
605
 
                    *pdf_xobj << "   /FormType 1\n";
606
 
                    *pdf_xobj << "   /BBox ["
607
 
                              << pbox->x0 << " "
608
 
                              << pbox->y0 << " "
609
 
                              << pbox->x1 << " "
610
 
                              << pbox->y1 << "]\n";
611
 
                    *pdf_xobj << "   /Group\n";
612
 
                    *pdf_xobj << "   << /Type /Group\n";
613
 
                    *pdf_xobj << "      /S /Transparency\n";
614
 
                    *pdf_xobj << "      /CS /DeviceGray \n";
615
 
                    *pdf_xobj << "   >>\n";
616
 
                    
617
 
                    Inkscape::SVGOStringStream os;
618
 
                    os.setf(std::ios::fixed);
619
 
                    
620
 
                    os << "q\n"
621
 
                       << pbox->x0 << " " << pbox->y0 << " m\n"
622
 
                       << pbox->x1 << " " << pbox->y0 << " l\n"
623
 
                       << pbox->x1 << " " << pbox->y1 << " l\n"
624
 
                       << pbox->x0 << " " << pbox->y1 << " l\n"
625
 
                       << pbox->x0 << " " << pbox->y0 << " l\n"
626
 
                       << "h\n"
627
 
                       << "W* n\n";
628
 
                    
629
 
                    SPGradient const *g = SP_GRADIENT(SP_STYLE_FILL_SERVER(style));
630
 
                    if (g->gradientTransform_set) {
631
 
                        os << g->gradientTransform[0] << " "
632
 
                           << g->gradientTransform[1] << " "
633
 
                           << g->gradientTransform[2] << " "
634
 
                           << g->gradientTransform[3] << " "
635
 
                           << g->gradientTransform[4] << " "
636
 
                           << g->gradientTransform[5] << " cm\n"; 
637
 
                    }
638
 
                    
639
 
                    os << pdf_alpha->get_name() << " sh\n";
640
 
                    os << "Q\n";
641
 
                    *pdf_xobj << "   /Length " << strlen(os.str().c_str()) << "\n";
642
 
                    *pdf_xobj << ">>\n";
643
 
                    *pdf_xobj << "stream\n";
644
 
                    *pdf_xobj << os.str().c_str();
645
 
                    *pdf_xobj << "endstream\n";
646
 
 
647
 
 
648
 
                    pdf_file->end_resource(pdf_alpha);
649
 
                    pdf_file->end_resource(pdf_smask);
650
 
                    pdf_file->end_resource(pdf_xobj);
651
 
                }
652
 
                
653
 
                *pdf_gstate << ">>\n";
654
 
 
655
 
                *page_stream << pdf_gstate->get_name() << " gs\n";
656
 
                    
657
 
                pdf_file->end_resource(pdf_gstate);
658
 
            }
659
 
        } else if (SP_IS_RADIALGRADIENT (SP_STYLE_FILL_SERVER (style))) {
660
 
 
661
 
            SPRadialGradient *rg=SP_RADIALGRADIENT(SP_STYLE_FILL_SERVER (style));
662
 
            sp_gradient_ensure_vector(SP_GRADIENT(rg)); // when exporting from commandline, vector is not built
663
 
 
664
 
            NR::Point c (rg->cx.computed, rg->cy.computed);
665
 
            NR::Point f (rg->fx.computed, rg->fy.computed);
666
 
            double r = rg->r.computed;
667
 
            if (pbox && SP_GRADIENT(rg)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
668
 
                // convert to userspace
669
 
                NR::Matrix bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
670
 
                c *= bbox2user;
671
 
                f *= bbox2user;
672
 
                r *= bbox2user.expansion();
673
 
            }
674
 
            
675
 
            double alpha = 1.0;
676
 
            for (gint i = 0; unsigned(i) < rg->vector.stops.size(); i++) {
677
 
                alpha *= rg->vector.stops[i].opacity;
678
 
            }
679
 
 
680
 
            if (alpha != 1.0 || style->opacity.set) {
681
 
                PdfObject *pdf_gstate = pdf_file->begin_resource(pdf_extgstate);
682
 
                *pdf_gstate << "<< /Type /ExtGState\n";
683
 
                
684
 
                if (style->opacity.set) {
685
 
                    *pdf_gstate << "   /ca " << SP_SCALE24_TO_FLOAT(style->opacity.value) << "\n";
686
 
                    *pdf_gstate << "   /AIS false\n";
687
 
                }
688
 
                
689
 
                if (alpha != 1.0) {
690
 
                    PdfObject *pdf_alpha = pdf_file->begin_resource(pdf_shading);
691
 
                    PdfObject *pdf_smask = pdf_file->begin_resource(pdf_none);
692
 
                    PdfObject *pdf_xobj = pdf_file->begin_resource(pdf_none);
693
 
 
694
 
 
695
 
                    *pdf_gstate << "   /SMask " << pdf_smask->get_id() << " 0 R\n";
696
 
 
697
 
 
698
 
                    *pdf_alpha << "<<\n/ShadingType 3\n/ColorSpace /DeviceGray\n";
699
 
                    *pdf_alpha << "/Coords ["<< f[NR::X] <<" "<< f[NR::Y] <<" 0 "<< c[NR::X] <<" "<< c[NR::Y] <<" "<< r <<"]\n";
700
 
                    *pdf_alpha << "/Extend [true true]\n";
701
 
                    *pdf_alpha << "/Domain [0 1]\n";
702
 
                    *pdf_alpha << "/Function <<\n/FunctionType 3\n/Functions\n[\n";
703
 
 
704
 
                    for (gint i = 0; unsigned(i) < rg->vector.stops.size() - 1; i++) {
705
 
                        *pdf_alpha << "<<\n/FunctionType 2\n/Domain [0 1]\n";
706
 
                        *pdf_alpha << "/C0 [" << rg->vector.stops[i].opacity << "]\n";
707
 
                        *pdf_alpha << "/C1 [" << rg->vector.stops[i+1].opacity << "]\n";
708
 
                        *pdf_alpha << "/N 1\n>>\n";
709
 
                    }
710
 
                    *pdf_alpha << "]\n/Domain [0 1]\n";
711
 
                    *pdf_alpha << "/Bounds [ ";
712
 
 
713
 
                    for (gint i=0;unsigned(i)<rg->vector.stops.size()-2;i++) {
714
 
                        *pdf_alpha << rg->vector.stops[i+1].offset <<" ";
715
 
                    }
716
 
                    *pdf_alpha << "]\n";
717
 
                    *pdf_alpha << "/Encode [ ";
718
 
                    for (gint i=0;unsigned(i)<rg->vector.stops.size()-1;i++) {
719
 
                        *pdf_alpha << "0 1 ";
720
 
                    }
721
 
                    *pdf_alpha << "]\n";
722
 
                    *pdf_alpha << ">>\n>>\n";
723
 
                    
724
 
                    
725
 
                    *pdf_smask << "<< /Type /Mask\n";
726
 
                    *pdf_smask << "   /S /Alpha\n";
727
 
                    *pdf_smask << "   /BC [0.0]\n";
728
 
                    *pdf_smask << "   /G " << pdf_xobj->get_id() << " 0 R\n";
729
 
                    *pdf_smask << ">>\n";
730
 
 
731
 
                    
732
 
                    *pdf_xobj << "<< /Type /XObject\n";
733
 
                    *pdf_xobj << "   /Subtype /Form\n";
734
 
                    *pdf_xobj << "   /FormType 1\n";
735
 
                    *pdf_xobj << "   /BBox ["
736
 
                              << pbox->x0 << " "
737
 
                              << pbox->y0 << " "
738
 
                              << pbox->x1 << " "
739
 
                              << pbox->y1 << "]\n";
740
 
                    *pdf_xobj << "   /Group\n";
741
 
                    *pdf_xobj << "   << /Type /Group\n";
742
 
                    *pdf_xobj << "      /S /Transparency\n";
743
 
                    *pdf_xobj << "      /CS /DeviceGray \n";
744
 
                    *pdf_xobj << "   >>\n";
745
 
                    
746
 
                    Inkscape::SVGOStringStream os;
747
 
                    os.setf(std::ios::fixed);
748
 
                    
749
 
                    os << "q\n"
750
 
                       << pbox->x0 << " " << pbox->y0 << " m\n"
751
 
                       << pbox->x1 << " " << pbox->y0 << " l\n"
752
 
                       << pbox->x1 << " " << pbox->y1 << " l\n"
753
 
                       << pbox->x0 << " " << pbox->y1 << " l\n"
754
 
                       << pbox->x0 << " " << pbox->y0 << " l\n"
755
 
                       << "h\n"
756
 
                       << "W* n\n";
757
 
                    
758
 
                    SPGradient const *g = SP_GRADIENT(SP_STYLE_FILL_SERVER(style));
759
 
                    if (g->gradientTransform_set) {
760
 
                        os << g->gradientTransform[0] << " "
761
 
                           << g->gradientTransform[1] << " "
762
 
                           << g->gradientTransform[2] << " "
763
 
                           << g->gradientTransform[3] << " "
764
 
                           << g->gradientTransform[4] << " "
765
 
                           << g->gradientTransform[5] << " cm\n"; 
766
 
                    }
767
 
                    
768
 
                    os << pdf_alpha->get_name() << " sh\n";
769
 
                    os << "Q\n";
770
 
                    *pdf_xobj << "   /Length " << strlen(os.str().c_str()) << "\n";
771
 
                    *pdf_xobj << ">>\n";
772
 
                    *pdf_xobj << "stream\n";
773
 
                    *pdf_xobj << os.str().c_str();
774
 
                    *pdf_xobj << "endstream\n";
775
 
 
776
 
 
777
 
                    pdf_file->end_resource(pdf_alpha);
778
 
                    pdf_file->end_resource(pdf_smask);
779
 
                    pdf_file->end_resource(pdf_xobj);
780
 
                }
781
 
                
782
 
                *pdf_gstate << ">>\n";
783
 
                
784
 
                *page_stream << pdf_gstate->get_name() << " gs\n";
785
 
                
786
 
                pdf_file->end_resource(pdf_gstate);
787
 
            }
788
 
        }
789
 
    }
790
 
}
791
 
 
792
 
void
793
 
PrintPDF::print_fill_style(SVGOStringStream &os, SPStyle const *const style, NRRect const *pbox)
794
 
{
795
 
    g_return_if_fail( style->fill.type == SP_PAINT_TYPE_COLOR
796
 
                      || ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
797
 
                           && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) ) );
798
 
    
799
 
    if (style->fill.type == SP_PAINT_TYPE_COLOR) {
800
 
        float rgb[3];
801
 
        sp_color_get_rgb_floatv(&style->fill.value.color, rgb);
802
 
 
803
 
        *page_stream << rgb[0] << " " << rgb[1] << " " << rgb[2] << " rg\n";
804
 
    } else {
805
 
        g_assert( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
806
 
                  && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) );
807
 
 
808
 
        if (SP_IS_LINEARGRADIENT (SP_STYLE_FILL_SERVER (style))) {
809
 
 
810
 
            SPLinearGradient *lg=SP_LINEARGRADIENT(SP_STYLE_FILL_SERVER (style));
811
 
            sp_gradient_ensure_vector(SP_GRADIENT(lg)); // when exporting from commandline, vector is not built
812
 
 
813
 
            NR::Point p1 (lg->x1.computed, lg->y1.computed);
814
 
            NR::Point p2 (lg->x2.computed, lg->y2.computed);
815
 
            if (pbox && SP_GRADIENT(lg)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
816
 
                // convert to userspace
817
 
                NR::Matrix bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
818
 
                p1 *= bbox2user;
819
 
                p2 *= bbox2user;
820
 
            }
821
 
 
822
 
            PdfObject *pdf_shade = pdf_file->begin_resource(pdf_shading);
823
 
 
824
 
            *pdf_shade << "<<\n/ShadingType 2\n/ColorSpace /DeviceRGB\n";
825
 
            *pdf_shade << "/Coords [" << p1[NR::X] << " " << p1[NR::Y] << " " << p2[NR::X] << " " << p2[NR::Y] <<"]\n";
826
 
            *pdf_shade << "/Extend [true true]\n";
827
 
            *pdf_shade << "/Domain [0 1]\n";
828
 
            *pdf_shade << "/Function <<\n/FunctionType 3\n/Functions\n[\n";
829
 
 
830
 
            for (gint i = 0; unsigned(i) < lg->vector.stops.size() - 1; i++) {
831
 
                float rgb[3];
832
 
                sp_color_get_rgb_floatv(&lg->vector.stops[i].color, rgb);
833
 
                *pdf_shade << "<<\n/FunctionType 2\n/Domain [0 1]\n";
834
 
                *pdf_shade << "/C0 [" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "]\n";
835
 
                sp_color_get_rgb_floatv(&lg->vector.stops[i+1].color, rgb);
836
 
                *pdf_shade << "/C1 [" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "]\n";
837
 
                *pdf_shade << "/N 1\n>>\n";
838
 
            }
839
 
            *pdf_shade << "]\n/Domain [0 1]\n";
840
 
            *pdf_shade << "/Bounds [ ";
841
 
            for (gint i=0;unsigned(i)<lg->vector.stops.size()-2;i++) {
842
 
                *pdf_shade << lg->vector.stops[i+1].offset <<" ";
843
 
            }
844
 
            *pdf_shade << "]\n";
845
 
            *pdf_shade << "/Encode [ ";
846
 
            for (gint i=0;unsigned(i)<lg->vector.stops.size()-1;i++) {
847
 
                *pdf_shade << "0 1 ";
848
 
            }
849
 
            *pdf_shade << "]\n";
850
 
            *pdf_shade << ">>\n>>\n";
851
 
            *page_stream << pdf_shade->get_name() << " ";
852
 
 
853
 
            pdf_file->end_resource(pdf_shade);
854
 
        } else if (SP_IS_RADIALGRADIENT (SP_STYLE_FILL_SERVER (style))) {
855
 
 
856
 
            SPRadialGradient *rg=SP_RADIALGRADIENT(SP_STYLE_FILL_SERVER (style));
857
 
            sp_gradient_ensure_vector(SP_GRADIENT(rg)); // when exporting from commandline, vector is not built
858
 
 
859
 
            NR::Point c (rg->cx.computed, rg->cy.computed);
860
 
            NR::Point f (rg->fx.computed, rg->fy.computed);
861
 
            double r = rg->r.computed;
862
 
            if (pbox && SP_GRADIENT(rg)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
863
 
                // convert to userspace
864
 
                NR::Matrix bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
865
 
                c *= bbox2user;
866
 
                f *= bbox2user;
867
 
                r *= bbox2user.expansion();
868
 
            }
869
 
 
870
 
            PdfObject *pdf_shade = pdf_file->begin_resource(pdf_shading);
871
 
 
872
 
            *pdf_shade << "<<\n/ShadingType 3\n/ColorSpace /DeviceRGB\n";
873
 
            *pdf_shade << "/Coords ["<< f[NR::X] <<" "<< f[NR::Y] <<" 0 "<< c[NR::X] <<" "<< c[NR::Y] <<" "<< r <<"]\n";
874
 
            *pdf_shade << "/Extend [true true]\n";
875
 
            *pdf_shade << "/Domain [0 1]\n";
876
 
            *pdf_shade << "/Function <<\n/FunctionType 3\n/Functions\n[\n";
877
 
 
878
 
            for (gint i = 0; unsigned(i) < rg->vector.stops.size() - 1; i++) {
879
 
                float rgb[3];
880
 
                sp_color_get_rgb_floatv(&rg->vector.stops[i].color, rgb);
881
 
                *pdf_shade << "<<\n/FunctionType 2\n/Domain [0 1]\n";
882
 
                *pdf_shade << "/C0 [" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "]\n";
883
 
                sp_color_get_rgb_floatv(&rg->vector.stops[i+1].color, rgb);
884
 
                *pdf_shade << "/C1 [" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "]\n";
885
 
                *pdf_shade << "/N 1\n>>\n";
886
 
            }
887
 
            *pdf_shade << "]\n/Domain [0 1]\n";
888
 
            *pdf_shade << "/Bounds [ ";
889
 
 
890
 
            for (gint i=0;unsigned(i)<rg->vector.stops.size()-2;i++) {
891
 
                *pdf_shade << rg->vector.stops[i+1].offset <<" ";
892
 
            }
893
 
            *pdf_shade << "]\n";
894
 
            *pdf_shade << "/Encode [ ";
895
 
            for (gint i=0;unsigned(i)<rg->vector.stops.size()-1;i++) {
896
 
                *pdf_shade << "0 1 ";
897
 
            }
898
 
            *pdf_shade << "]\n";
899
 
            *pdf_shade << ">>\n>>\n";
900
 
 
901
 
            *page_stream << pdf_shade->get_name() << " ";
902
 
 
903
 
            pdf_file->end_resource(pdf_shade);
904
 
        }
905
 
    }
906
 
}
907
 
 
908
 
void
909
 
PrintPDF::print_stroke_style(SVGOStringStream &os, SPStyle const *style)
910
 
{
911
 
    float rgb[3];
912
 
    
913
 
    sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
914
 
    *page_stream << rgb[0] << " " << rgb[1] << " " << rgb[2] << " RG\n";
915
 
        
916
 
    float alpha = 1.0;
917
 
 
918
 
    if (style->opacity.set)
919
 
        alpha *= SP_SCALE24_TO_FLOAT(style->opacity.value);
920
 
        
921
 
    if (style->stroke_opacity.set)
922
 
        alpha *= SP_SCALE24_TO_FLOAT(style->stroke_opacity.value);
923
 
 
924
 
    if (alpha != 1.0) {
925
 
        PdfObject *pdf_alpha = pdf_file->begin_resource(pdf_extgstate);
926
 
        *pdf_alpha << "<< /Type /ExtGState\n";
927
 
        *pdf_alpha << "   /CA " << alpha << "\n";
928
 
        *pdf_alpha << "   /AIS false\n";
929
 
        *pdf_alpha << ">>\n";
930
 
        
931
 
        *page_stream << pdf_alpha->get_name() << " gs\n";
932
 
        
933
 
        pdf_file->end_resource(pdf_alpha);
934
 
    }
935
 
 
936
 
    // There are rare cases in which for a solid line stroke_dasharray_set is true. To avoid
937
 
    // invalid PS-lines such as "[0.0000000 0.0000000] 0.0000000 setdash", which should be "[] 0 setdash",
938
 
    // we first check if all components of stroke_dash.dash are 0.
939
 
    bool LineSolid = true;
940
 
    if (style->stroke_dash.n_dash   &&
941
 
        style->stroke_dash.dash       )
942
 
    {
943
 
        int i = 0;
944
 
        while (LineSolid && (i < style->stroke_dash.n_dash)) {
945
 
                if (style->stroke_dash.dash[i] > 0.00000001)
946
 
                    LineSolid = false;
947
 
                i++;
948
 
        }
949
 
        if (!LineSolid) {
950
 
            *page_stream << "[";
951
 
            for (i = 0; i < style->stroke_dash.n_dash; i++) {
952
 
                if (i > 0) {
953
 
                    *page_stream << " ";
954
 
                }
955
 
                *page_stream << style->stroke_dash.dash[i];
956
 
            }
957
 
            *page_stream << "] " << style->stroke_dash.offset << " d\n";
958
 
        } else {
959
 
            *page_stream << "[] 0 d\n";
960
 
        }
961
 
    } else {
962
 
        *page_stream << "[] 0 d\n";
963
 
    }
964
 
 
965
 
    *page_stream << style->stroke_width.computed << " w\n";
966
 
    *page_stream << style->stroke_linejoin.computed << " j\n";
967
 
    *page_stream << style->stroke_linecap.computed << " J\n";
968
 
    *page_stream <<
969
 
        ( style->stroke_miterlimit.value > 1 ?
970
 
          style->stroke_miterlimit.value : 1 ) << " M\n";
971
 
}
972
 
 
973
 
 
974
 
unsigned int
975
 
PrintPDF::fill(Inkscape::Extension::Print *mod, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *const style,
976
 
              NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
977
 
{
978
 
    Inkscape::SVGOStringStream os;
979
 
    os.setf(std::ios::fixed);
980
 
 
981
 
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
982
 
    if (_bitmap) return 0;
983
 
 
984
 
    if ( style->fill.type == SP_PAINT_TYPE_COLOR ) {
985
 
        *page_stream << "q\n";
986
 
        print_fill_style(os, style, pbox);
987
 
        print_fill_alpha(os, style, pbox);
988
 
        print_bpath(os, bpath->path);
989
 
        if (style->fill_rule.value == SP_WIND_RULE_EVENODD) {
990
 
            *page_stream << "f*\n";
991
 
        } else {
992
 
            *page_stream << "f\n";
993
 
        }
994
 
        *page_stream << "Q\n";
995
 
    }
996
 
    else if ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
997
 
              && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) )
998
 
    {
999
 
        *page_stream << "q\n";
1000
 
        print_bpath(os, bpath->path);
1001
 
 
1002
 
        if (style->fill_rule.value == SP_WIND_RULE_EVENODD) {
1003
 
            g_assert( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
1004
 
                      && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) );
1005
 
            SPGradient const *g = SP_GRADIENT(SP_STYLE_FILL_SERVER(style));
1006
 
            *page_stream << "W* n\n";
1007
 
            print_fill_alpha(os, style, pbox);
1008
 
            if (g->gradientTransform_set) {
1009
 
                *page_stream << "q\n";
1010
 
                *page_stream << g->gradientTransform[0] << " "
1011
 
                             << g->gradientTransform[1] << " "
1012
 
                             << g->gradientTransform[2] << " "
1013
 
                             << g->gradientTransform[3] << " "
1014
 
                             << g->gradientTransform[4] << " "
1015
 
                             << g->gradientTransform[5] << " cm\n";
1016
 
            }
1017
 
            print_fill_style(os, style, pbox);
1018
 
            *page_stream << "sh\n";
1019
 
            if (g->gradientTransform_set) {
1020
 
                *page_stream << "Q\n";
1021
 
            }
1022
 
        } else {
1023
 
            g_assert( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
1024
 
                      && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) );
1025
 
            SPGradient const *g = SP_GRADIENT(SP_STYLE_FILL_SERVER(style));
1026
 
            *page_stream << "W n\n";
1027
 
            print_fill_alpha(os, style, pbox);
1028
 
            if (g->gradientTransform_set) {
1029
 
                *page_stream << "q\n";
1030
 
                *page_stream << g->gradientTransform[0] << " "
1031
 
                             << g->gradientTransform[1] << " "
1032
 
                             << g->gradientTransform[2] << " "
1033
 
                             << g->gradientTransform[3] << " "
1034
 
                             << g->gradientTransform[4] << " "
1035
 
                             << g->gradientTransform[5] << " cm\n"; 
1036
 
            }
1037
 
            print_fill_style(os, style, pbox);
1038
 
            *page_stream << "sh\n";
1039
 
            if (g->gradientTransform_set) {
1040
 
                *page_stream << "Q\n";
1041
 
            }
1042
 
        }
1043
 
 
1044
 
        *page_stream << "Q\n";
1045
 
    }        
1046
 
 
1047
 
    return 0;
1048
 
}
1049
 
 
1050
 
 
1051
 
unsigned int
1052
 
PrintPDF::stroke(Inkscape::Extension::Print *mod, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *style,
1053
 
                NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
1054
 
{
1055
 
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
1056
 
    if (_bitmap) return 0;
1057
 
 
1058
 
    if (style->stroke.type == SP_PAINT_TYPE_COLOR) {
1059
 
        Inkscape::SVGOStringStream os;
1060
 
        os.setf(std::ios::fixed);
1061
 
 
1062
 
        *page_stream << "q\n";
1063
 
 
1064
 
        print_stroke_style(os, style);
1065
 
        print_bpath(os, bpath->path);
1066
 
        *page_stream << "S\n";
1067
 
 
1068
 
        *page_stream << "Q\n";
1069
 
    }
1070
 
 
1071
 
    return 0;
1072
 
}
1073
 
 
1074
 
unsigned int
1075
 
PrintPDF::image(Inkscape::Extension::Print *mod, guchar *px, unsigned int w, unsigned int h, unsigned int rs,
1076
 
               NRMatrix const *transform, SPStyle const *style)
1077
 
{
1078
 
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
1079
 
    if (_bitmap) return 0;
1080
 
 
1081
 
    return 0;
1082
 
    
1083
 
    return print_image(_stream, px, w, h, rs, transform);
1084
 
#if 0
1085
 
    fprintf(_stream, "gsave\n");
1086
 
    fprintf(_stream, "/rowdata %d string def\n", 3 * w);
1087
 
    fprintf(_stream, "[%g %g %g %g %g %g] concat\n",
1088
 
            transform->c[0],
1089
 
            transform->c[1],
1090
 
            transform->c[2],
1091
 
            transform->c[3],
1092
 
            transform->c[4],
1093
 
            transform->c[5]);
1094
 
    fprintf(_stream, "%d %d 8 [%d 0 0 -%d 0 %d]\n", w, h, w, h, h);
1095
 
    fprintf(_stream, "{currentfile rowdata readhexstring pop}\n");
1096
 
    fprintf(_stream, "false 3 colorimage\n");
1097
 
 
1098
 
    for (unsigned int r = 0; r < h; r++) {
1099
 
        guchar *s;
1100
 
        unsigned int c0, c1, c;
1101
 
        s = px + r * rs;
1102
 
        for (c0 = 0; c0 < w; c0 += 24) {
1103
 
            c1 = MIN(w, c0 + 24);
1104
 
            for (c = c0; c < c1; c++) {
1105
 
                static char const xtab[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1106
 
                fputc(xtab[s[0] >> 4], _stream);
1107
 
                fputc(xtab[s[0] & 0xf], _stream);
1108
 
                fputc(xtab[s[1] >> 4], _stream);
1109
 
                fputc(xtab[s[1] & 0xf], _stream);
1110
 
                fputc(xtab[s[2] >> 4], _stream);
1111
 
                fputc(xtab[s[2] & 0xf], _stream);
1112
 
                s += 4;
1113
 
            }
1114
 
            fputs("\n", _stream);
1115
 
        }
1116
 
    }
1117
 
 
1118
 
    fprintf(_stream, "grestore\n");
1119
 
 
1120
 
    return 0;
1121
 
#endif
1122
 
}
1123
 
 
1124
 
char const *
1125
 
PrintPDF::PSFontName(SPStyle const *style)
1126
 
{
1127
 
    font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value, font_style_to_pos(*style));
1128
 
 
1129
 
    char const *n;
1130
 
    char name_buf[256];
1131
 
 
1132
 
    if (tf) {
1133
 
        tf->PSName(name_buf, sizeof(name_buf));
1134
 
        n = name_buf;
1135
 
        tf->Unref();
1136
 
    } else {
1137
 
        // this system does not have this font, so just use the name from SVG in the hope that PS interpreter will make sense of it
1138
 
        bool i = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC);
1139
 
        bool o = (style->font_style.value == SP_CSS_FONT_STYLE_OBLIQUE);
1140
 
        bool b = (style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLD) ||
1141
 
            (style->font_weight.value >= SP_CSS_FONT_WEIGHT_500 && style->font_weight.value <= SP_CSS_FONT_WEIGHT_900);
1142
 
 
1143
 
        n = g_strdup_printf("%s%s%s%s",
1144
 
                            g_strdelimit(style->text->font_family.value, " ", '-'),
1145
 
                            (b || i || o) ? "-" : "",
1146
 
                            (b) ? "Bold" : "",
1147
 
                            (i) ? "Italic" : ((o) ? "Oblique" : "") );
1148
 
    }
1149
 
 
1150
 
    return g_strdup(n);
1151
 
}
1152
 
 
1153
 
 
1154
 
unsigned int
1155
 
PrintPDF::text(Inkscape::Extension::Print *mod, char const *text, NR::Point p,
1156
 
              SPStyle const *const style)
1157
 
{
1158
 
    if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
1159
 
    if (_bitmap) return 0;
1160
 
 
1161
 
    Inkscape::SVGOStringStream os;
1162
 
    os.setf(std::ios::fixed);
1163
 
 
1164
 
    return 0;
1165
 
    
1166
 
    // Escape chars
1167
 
    Inkscape::SVGOStringStream escaped_text;
1168
 
    escaped_text.setf(std::ios::fixed);
1169
 
    
1170
 
    escaped_text << std::oct;
1171
 
    for (gchar const *p_text = text ; *p_text ; p_text = g_utf8_next_char(p_text)) {
1172
 
        gunichar const c = g_utf8_get_char(p_text);
1173
 
        if (c == '\\' || c == ')' || c == '(')
1174
 
            escaped_text << '\\' << static_cast<char>(c);
1175
 
        else if (c >= 0x80)
1176
 
            escaped_text << '\\' << c;
1177
 
        else
1178
 
            escaped_text << static_cast<char>(c);
1179
 
    }
1180
 
 
1181
 
    os << "gsave\n";
1182
 
 
1183
 
    // set font
1184
 
    char const *fn = PSFontName(style);
1185
 
    if (_latin1_encoded_fonts.find(fn) == _latin1_encoded_fonts.end()) {
1186
 
        if (!_newlatin1font_proc_defined) {
1187
 
            // input: newfontname, existingfontname
1188
 
            // output: new font object, also defined to newfontname
1189
 
            os << "/newlatin1font "         // name of the proc
1190
 
                  "{findfont dup length dict copy "     // load the font and create a copy of it
1191
 
                  "dup /Encoding ISOLatin1Encoding put "     // change the encoding in the copy
1192
 
                  "definefont} def\n";      // create the new font and leave it on the stack, define the proc
1193
 
            _newlatin1font_proc_defined = true;
1194
 
        }
1195
 
        os << "/" << fn << "-ISOLatin1 /" << fn << " newlatin1font\n";
1196
 
        _latin1_encoded_fonts.insert(fn);
1197
 
    } else
1198
 
        os << "/" << fn << "-ISOLatin1 findfont\n";
1199
 
    os << style->font_size.computed << " scalefont\n";
1200
 
    os << "setfont\n";
1201
 
    g_free((void *) fn);
1202
 
 
1203
 
    if ( style->fill.type == SP_PAINT_TYPE_COLOR
1204
 
         || ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
1205
 
              && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) ) )
1206
 
    {
1207
 
        // set fill style
1208
 
        print_fill_style(os, style, NULL);
1209
 
        // FIXME: we don't know the pbox of text, so have to pass NULL. This means gradients with
1210
 
        // bbox units won't work with text. However userspace gradients don't work with text either
1211
 
        // (text is black) for some reason.
1212
 
 
1213
 
        os << "newpath\n";
1214
 
        os << p[NR::X] << " " << p[NR::Y] << " moveto\n";
1215
 
        os << "(" << escaped_text.str() << ") show\n";
1216
 
    }
1217
 
 
1218
 
    if (style->stroke.type == SP_PAINT_TYPE_COLOR) {
1219
 
 
1220
 
        // set stroke style
1221
 
        print_stroke_style(os, style);
1222
 
 
1223
 
        // paint stroke
1224
 
        os << "newpath\n";
1225
 
        os << p[NR::X] << " " << p[NR::Y] << " moveto\n";
1226
 
        os << "(" << escaped_text.str() << ") false charpath stroke\n";
1227
 
    }
1228
 
 
1229
 
    os << "grestore\n";
1230
 
 
1231
 
    fprintf(_stream, "%s", os.str().c_str());
1232
 
 
1233
 
    return 0;
1234
 
}
1235
 
 
1236
 
 
1237
 
 
1238
 
/* PDF helpers */
1239
 
 
1240
 
void
1241
 
PrintPDF::print_bpath(SVGOStringStream &os, NArtBpath const *bp)
1242
 
{
1243
 
    bool closed = false;
1244
 
    while (bp->code != NR_END) {
1245
 
        switch (bp->code) {
1246
 
            case NR_MOVETO:
1247
 
                if (closed) {
1248
 
                    *page_stream << "h\n";
1249
 
                }
1250
 
                closed = true;
1251
 
                *page_stream << bp->x3 << " " << bp->y3 << " m\n";
1252
 
                break;
1253
 
            case NR_MOVETO_OPEN:
1254
 
                if (closed) {
1255
 
                    *page_stream << "h\n";
1256
 
                }
1257
 
                closed = false;
1258
 
                *page_stream << bp->x3 << " " << bp->y3 << " m\n";
1259
 
                break;
1260
 
            case NR_LINETO:
1261
 
                *page_stream << bp->x3 << " " << bp->y3 << " l\n";
1262
 
                break;
1263
 
            case NR_CURVETO:
1264
 
                *page_stream << bp->x1 << " " << bp->y1 << " "
1265
 
                   << bp->x2 << " " << bp->y2 << " "
1266
 
                   << bp->x3 << " " << bp->y3 << " c\n";
1267
 
                break;
1268
 
            default:
1269
 
                break;
1270
 
        }
1271
 
        bp += 1;
1272
 
    }
1273
 
    if (closed) {
1274
 
        *page_stream << "h\n";
1275
 
    }
1276
 
}
1277
 
 
1278
 
/* The following code is licensed under GNU GPL.
1279
 
** The packbits, ascii85 and imaging printing code
1280
 
** is from the gimp's postscript.c.
1281
 
*/
1282
 
 
1283
 
/**
1284
 
* \param nin Number of bytes of source data.
1285
 
* \param src Source data.
1286
 
* \param nout Number of output bytes.
1287
 
* \param dst Buffer for output.
1288
 
*/
1289
 
void
1290
 
PrintPDF::compress_packbits(int nin,
1291
 
                           guchar *src,
1292
 
                           int *nout,
1293
 
                           guchar *dst)
1294
 
 
1295
 
{
1296
 
    register guchar c;
1297
 
    int nrepeat, nliteral;
1298
 
    guchar *run_start;
1299
 
    guchar *start_dst = dst;
1300
 
    guchar *last_literal = NULL;
1301
 
 
1302
 
    for (;;) {
1303
 
        if (nin <= 0) break;
1304
 
 
1305
 
        run_start = src;
1306
 
        c = *run_start;
1307
 
 
1308
 
        /* Search repeat bytes */
1309
 
        if ((nin > 1) && (c == src[1])) {
1310
 
            nrepeat = 1;
1311
 
            nin -= 2;
1312
 
            src += 2;
1313
 
            while ((nin > 0) && (c == *src)) {
1314
 
                nrepeat++;
1315
 
                src++;
1316
 
                nin--;
1317
 
                if (nrepeat == 127) break; /* Maximum repeat */
1318
 
            }
1319
 
 
1320
 
            /* Add two-byte repeat to last literal run ? */
1321
 
            if ( (nrepeat == 1)
1322
 
                 && (last_literal != NULL) && (((*last_literal)+1)+2 <= 128) )
1323
 
            {
1324
 
                *last_literal += 2;
1325
 
                *(dst++) = c;
1326
 
                *(dst++) = c;
1327
 
                continue;
1328
 
            }
1329
 
 
1330
 
            /* Add repeat run */
1331
 
            *(dst++) = (guchar)((-nrepeat) & 0xff);
1332
 
            *(dst++) = c;
1333
 
            last_literal = NULL;
1334
 
            continue;
1335
 
        }
1336
 
        /* Search literal bytes */
1337
 
        nliteral = 1;
1338
 
        nin--;
1339
 
        src++;
1340
 
 
1341
 
        for (;;) {
1342
 
            if (nin <= 0) break;
1343
 
 
1344
 
            if ((nin >= 2) && (src[0] == src[1])) /* A two byte repeat ? */
1345
 
                break;
1346
 
 
1347
 
            nliteral++;
1348
 
            nin--;
1349
 
            src++;
1350
 
            if (nliteral == 128) break; /* Maximum literal run */
1351
 
        }
1352
 
 
1353
 
        /* Could be added to last literal run ? */
1354
 
        if ((last_literal != NULL) && (((*last_literal)+1)+nliteral <= 128)) {
1355
 
            *last_literal += nliteral;
1356
 
        } else {
1357
 
            last_literal = dst;
1358
 
            *(dst++) = (guchar)(nliteral-1);
1359
 
        }
1360
 
        while (nliteral-- > 0) *(dst++) = *(run_start++);
1361
 
    }
1362
 
    *nout = dst - start_dst;
1363
 
}
1364
 
 
1365
 
void
1366
 
PrintPDF::ascii85_init(void)
1367
 
{
1368
 
    ascii85_len = 0;
1369
 
    ascii85_linewidth = 0;
1370
 
}
1371
 
 
1372
 
void
1373
 
PrintPDF::ascii85_flush(SVGOStringStream &os)
1374
 
{
1375
 
    char c[5];
1376
 
    bool const zero_case = (ascii85_buf == 0);
1377
 
    static int const max_linewidth = 75;
1378
 
 
1379
 
    for (int i = 4; i >= 0; i--) {
1380
 
        c[i] = (ascii85_buf % 85) + '!';
1381
 
        ascii85_buf /= 85;
1382
 
    }
1383
 
    /* check for special case: "!!!!!" becomes "z", but only if not
1384
 
     * at end of data. */
1385
 
    if (zero_case && (ascii85_len == 4)) {
1386
 
        if (ascii85_linewidth >= max_linewidth) {
1387
 
            os << '\n';
1388
 
            ascii85_linewidth = 0;
1389
 
        }
1390
 
        os << 'z';
1391
 
        ascii85_linewidth++;
1392
 
    } else {
1393
 
        for (int i = 0; i < ascii85_len+1; i++) {
1394
 
            if ((ascii85_linewidth >= max_linewidth) && (c[i] != '%')) {
1395
 
                os << '\n';
1396
 
                ascii85_linewidth = 0;
1397
 
            }
1398
 
            os << c[i];
1399
 
            ascii85_linewidth++;
1400
 
        }
1401
 
    }
1402
 
 
1403
 
    ascii85_len = 0;
1404
 
    ascii85_buf = 0;
1405
 
}
1406
 
 
1407
 
inline void
1408
 
PrintPDF::ascii85_out(guchar byte, SVGOStringStream &os)
1409
 
{
1410
 
    if (ascii85_len == 4)
1411
 
        ascii85_flush(os);
1412
 
 
1413
 
    ascii85_buf <<= 8;
1414
 
    ascii85_buf |= byte;
1415
 
    ascii85_len++;
1416
 
}
1417
 
 
1418
 
void
1419
 
PrintPDF::ascii85_nout(int n, guchar *uptr, SVGOStringStream &os)
1420
 
{
1421
 
    while (n-- > 0) {
1422
 
        ascii85_out(*uptr, os);
1423
 
        uptr++;
1424
 
    }
1425
 
}
1426
 
 
1427
 
void
1428
 
PrintPDF::ascii85_done(SVGOStringStream &os)
1429
 
{
1430
 
    if (ascii85_len) {
1431
 
        /* zero any unfilled buffer portion, then flush */
1432
 
        ascii85_buf <<= (8 * (4-ascii85_len));
1433
 
        ascii85_flush(os);
1434
 
    }
1435
 
 
1436
 
    os << "~>\n";
1437
 
}
1438
 
 
1439
 
unsigned int
1440
 
PrintPDF::print_image(FILE *ofp, guchar *px, unsigned int width, unsigned int height, unsigned int rs,
1441
 
                     NRMatrix const *transform)
1442
 
{
1443
 
    Inkscape::SVGOStringStream os;
1444
 
    os.setf(std::ios::fixed);
1445
 
 
1446
 
    return 0;
1447
 
    
1448
 
    os << "gsave\n";
1449
 
    os << "[" << transform->c[0] << " "
1450
 
       << transform->c[1] << " "
1451
 
       << transform->c[2] << " "
1452
 
       << transform->c[3] << " "
1453
 
       << transform->c[4] << " "
1454
 
       << transform->c[5] << "] concat\n";
1455
 
    os << width << " " << height << " 8 ["
1456
 
       << width << " 0 0 -" << height << " 0 " << height << "]\n";
1457
 
 
1458
 
 
1459
 
    /* Write read image procedure */
1460
 
    os << "% Strings to hold RGB-samples per scanline\n";
1461
 
    os << "/rstr " << width << " string def\n";
1462
 
    os << "/gstr " << width << " string def\n";
1463
 
    os << "/bstr " << width << " string def\n";
1464
 
    os << "{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}\n";
1465
 
    os << "{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}\n";
1466
 
    os << "{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}\n";
1467
 
    os << "true 3\n";
1468
 
 
1469
 
    /* Allocate buffer for packbits data. Worst case: Less than 1% increase */
1470
 
    guchar *const packb = (guchar *)g_malloc((width * 105)/100+2);
1471
 
    guchar *const plane = (guchar *)g_malloc(width);
1472
 
 
1473
 
    /* ps_begin_data(ofp); */
1474
 
    os << "colorimage\n";
1475
 
 
1476
 
/*#define GET_RGB_TILE(begin)                   \
1477
 
 *  {int scan_lines;                                                    \
1478
 
 *    scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
1479
 
 *    gimp_pixel_rgn_get_rect(&pixel_rgn, begin, 0, i, width, scan_lines); \
1480
 
 *    src = begin; }
1481
 
 */
1482
 
 
1483
 
    for (unsigned i = 0; i < height; i++) {
1484
 
        /* if ((i % tile_height) == 0) GET_RGB_TILE(data); */ /* Get more data */
1485
 
        guchar const *const src = px + i * rs;
1486
 
 
1487
 
        /* Iterate over RGB */
1488
 
        for (int rgb = 0; rgb < 3; rgb++) {
1489
 
            guchar const *src_ptr = src + rgb;
1490
 
            guchar *plane_ptr = plane;
1491
 
            for (unsigned j = 0; j < width; j++) {
1492
 
                *(plane_ptr++) = *src_ptr;
1493
 
                src_ptr += 4;
1494
 
            }
1495
 
 
1496
 
            int nout;
1497
 
            compress_packbits(width, plane, &nout, packb);
1498
 
 
1499
 
            ascii85_init();
1500
 
            ascii85_nout(nout, packb, os);
1501
 
            ascii85_out(128, os); /* Write EOD of RunLengthDecode filter */
1502
 
            ascii85_done(os);
1503
 
        }
1504
 
    }
1505
 
    /* ps_end_data(ofp); */
1506
 
 
1507
 
#if 0
1508
 
    fprintf(ofp, "showpage\n");
1509
 
    g_free(data);
1510
 
#endif
1511
 
 
1512
 
    g_free(packb);
1513
 
    g_free(plane);
1514
 
 
1515
 
#if 0
1516
 
    if (ferror(ofp)) {
1517
 
        g_message(_("write error occurred"));
1518
 
        return (FALSE);
1519
 
    }
1520
 
#endif
1521
 
 
1522
 
    os << "grestore\n";
1523
 
 
1524
 
    fprintf(ofp, "%s", os.str().c_str());
1525
 
 
1526
 
    return 0;
1527
 
//#undef GET_RGB_TILE
1528
 
}
1529
 
 
1530
 
bool
1531
 
PrintPDF::textToPath(Inkscape::Extension::Print * ext)
1532
 
{
1533
 
    return ext->get_param_bool("textToPath");
1534
 
}
1535
 
 
1536
 
#include "clear-n_.h"
1537
 
 
1538
 
void
1539
 
PrintPDF::init(void)
1540
 
{
1541
 
    /* SVG in */
1542
 
    (void) Inkscape::Extension::build_from_mem(
1543
 
        "<inkscape-extension>\n"
1544
 
        "<name>" N_("PDF Print") "</name>\n"
1545
 
        "<id>" SP_MODULE_KEY_PRINT_PDF "</id>\n"
1546
 
        "<param name=\"bitmap\" type=\"boolean\">FALSE</param>\n"
1547
 
        "<param name=\"resolution\" type=\"string\">72</param>\n"
1548
 
        "<param name=\"destination\" type=\"string\">| lp</param>\n"
1549
 
        "<param name=\"pageBoundingBox\" type=\"boolean\">TRUE</param>\n"
1550
 
        "<param name=\"textToPath\" type=\"boolean\">TRUE</param>\n"
1551
 
        "<print/>\n"
1552
 
        "</inkscape-extension>", new PrintPDF());
1553
 
}
1554
 
 
1555
 
 
1556
 
}  /* namespace Internal */
1557
 
}  /* namespace Extension */
1558
 
}  /* namespace Inkscape */
1559
 
 
1560
 
/* End of GNU GPL code */
1561
 
 
1562
 
 
1563
 
/*
1564
 
  Local Variables:
1565
 
  mode:c++
1566
 
  c-file-style:"stroustrup"
1567
 
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1568
 
  indent-tabs-mode:nil
1569
 
  fill-column:99
1570
 
  End:
1571
 
*/
1572
 
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :