Code

Added a PDF import settings dialog
authormiklosh <miklosh@users.sourceforge.net>
Sun, 19 Aug 2007 12:50:15 +0000 (12:50 +0000)
committermiklosh <miklosh@users.sourceforge.net>
Sun, 19 Aug 2007 12:50:15 +0000 (12:50 +0000)
src/extension/internal/pdfinput/pdf-input.cpp
src/extension/internal/pdfinput/pdf-input.h
src/extension/internal/pdfinput/svg-builder.cpp
src/extension/internal/pdfinput/svg-builder.h

index 47057cccf09584c8f777f9701a439cea33466ebb..75940ff56f2f9ecad8d6c54f2cdde14b7f11bd00 100644 (file)
 
 #include "document-private.h"
 
+#include <gtk/gtkdialog.h>
+
 namespace Inkscape {
 namespace Extension {
 namespace Internal {
 
 /**
- * Parses the first page of the given PDF document using PdfParser.
+ * \brief The PDF import dialog
+ * FIXME: Probably this should be placed into src/ui/dialog
+ */
+
+static Glib::ustring crop_setting_choices[] = {
+    Glib::ustring(_("media box")),
+    Glib::ustring(_("crop box")),
+    Glib::ustring(_("trim box")),
+    Glib::ustring(_("bleed box")),
+    Glib::ustring(_("art box"))
+};
+
+PdfImportDialog::PdfImportDialog(PDFDoc *doc)
+{
+
+    _pdf_doc = doc;
+
+    cancelbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-cancel")));
+    okbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-ok")));
+    _labelSelect = Gtk::manage(new class Gtk::Label(_("Select page:")));
+
+    // Page number
+    Gtk::Adjustment *_pageNumberSpin_adj = Gtk::manage(
+            new class Gtk::Adjustment(1, 1, _pdf_doc->getNumPages(), 1, 10, 0));
+    _pageNumberSpin = Gtk::manage(new class Gtk::SpinButton(*_pageNumberSpin_adj, 1, 1));
+    hbox2 = Gtk::manage(new class Gtk::HBox(false, 0));
+
+    // Crop settings
+    _cropCheck = Gtk::manage(new class Gtk::CheckButton(_("Crop to:")));
+    _cropTypeCombo = Gtk::manage(new class Gtk::ComboBoxText());
+    int num_crop_choices = sizeof(crop_setting_choices) / sizeof(crop_setting_choices[0]);
+    for ( int i = 0 ; i < num_crop_choices ; i++ ) {
+        _cropTypeCombo->append_text(crop_setting_choices[i]);
+    }
+    _cropTypeCombo->set_active_text(crop_setting_choices[0]);
+    _cropTypeCombo->set_sensitive(false);
+
+    hbox3 = Gtk::manage(new class Gtk::HBox(false, 0));
+    vbox2 = Gtk::manage(new class Gtk::VBox(false, 0));
+    alignment3 = Gtk::manage(new class Gtk::Alignment(0.5, 0.5, 1, 1));
+    _labelPageSettings = Gtk::manage(new class Gtk::Label(_("Page Settings")));
+    _pageSettingsFrame = Gtk::manage(new class Gtk::Frame());
+    _labelPrecision = Gtk::manage(new class Gtk::Label(_("Precision of approximation for gradient meshes:")));
+   
+    _fallbackPrecisionSlider_adj = Gtk::manage(new class Gtk::Adjustment(2, 1, 256, 1, 10, 10));
+    _fallbackPrecisionSlider = Gtk::manage(new class Gtk::HScale(*_fallbackPrecisionSlider_adj));
+    _fallbackPrecisionSlider->set_value(2.0);
+    _labelPrecisionComment = Gtk::manage(new class Gtk::Label(_("rough")));
+    hbox6 = Gtk::manage(new class Gtk::HBox(false, 0));
+
+    // Text options
+    _labelText = Gtk::manage(new class Gtk::Label(_("Text handling:")));
+    _textHandlingCombo = Gtk::manage(new class Gtk::ComboBoxText());
+    _textHandlingCombo->append_text(_("import text as text"));
+    _textHandlingCombo->set_active_text(_("import text as text"));
+    
+    hbox5 = Gtk::manage(new class Gtk::HBox(false, 0));
+    _embedImagesCheck = Gtk::manage(new class Gtk::CheckButton(_("Embed images")));
+    vbox3 = Gtk::manage(new class Gtk::VBox(false, 0));
+    alignment4 = Gtk::manage(new class Gtk::Alignment(0.5, 0.5, 1, 1));
+    _labelImportSettings = Gtk::manage(new class Gtk::Label(_("Import Settings")));
+    _importSettingsFrame = Gtk::manage(new class Gtk::Frame());
+    vbox1 = Gtk::manage(new class Gtk::VBox(false, 0));
+    _previewArea = Gtk::manage(new class Gtk::DrawingArea());
+    hbox1 = Gtk::manage(new class Gtk::HBox(false, 0));
+    cancelbutton->set_flags(Gtk::CAN_FOCUS);
+    cancelbutton->set_flags(Gtk::CAN_DEFAULT);
+    cancelbutton->set_relief(Gtk::RELIEF_NORMAL);
+    okbutton->set_flags(Gtk::CAN_FOCUS);
+    okbutton->set_flags(Gtk::CAN_DEFAULT);
+    okbutton->set_relief(Gtk::RELIEF_NORMAL);
+    this->get_action_area()->property_layout_style().set_value(Gtk::BUTTONBOX_END);
+    _labelSelect->set_alignment(0.5,0.5);
+    _labelSelect->set_padding(0,0);
+    _labelSelect->set_justify(Gtk::JUSTIFY_LEFT);
+    _labelSelect->set_line_wrap(false);
+    _labelSelect->set_use_markup(false);
+    _labelSelect->set_selectable(false);
+    _pageNumberSpin->set_flags(Gtk::CAN_FOCUS);
+    _pageNumberSpin->set_update_policy(Gtk::UPDATE_ALWAYS);
+    _pageNumberSpin->set_numeric(true);
+    _pageNumberSpin->set_digits(0);
+    _pageNumberSpin->set_wrap(false);
+    hbox2->pack_start(*_labelSelect, Gtk::PACK_SHRINK, 0);
+    hbox2->pack_start(*_pageNumberSpin, Gtk::PACK_SHRINK, 4);
+    _cropCheck->set_flags(Gtk::CAN_FOCUS);
+    _cropCheck->set_relief(Gtk::RELIEF_NORMAL);
+    _cropCheck->set_mode(true);
+    _cropCheck->set_active(false);
+    _cropTypeCombo->set_border_width(1);
+    hbox3->pack_start(*_cropCheck, Gtk::PACK_SHRINK, 0);
+    hbox3->pack_start(*_cropTypeCombo, Gtk::PACK_SHRINK, 4);
+    vbox2->pack_start(*hbox2);
+    vbox2->pack_start(*hbox3);
+    alignment3->add(*vbox2);
+    _labelPageSettings->set_alignment(0.5,0.5);
+    _labelPageSettings->set_padding(0,0);
+    _labelPageSettings->set_justify(Gtk::JUSTIFY_LEFT);
+    _labelPageSettings->set_line_wrap(false);
+    _labelPageSettings->set_use_markup(true);
+    _labelPageSettings->set_selectable(false);
+    _pageSettingsFrame->set_border_width(4);
+    _pageSettingsFrame->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
+    _pageSettingsFrame->set_label_align(0,0.5);
+    _pageSettingsFrame->add(*alignment3);
+    _pageSettingsFrame->set_label_widget(*_labelPageSettings);
+    _labelPrecision->set_alignment(0.5,0.5);
+    _labelPrecision->set_padding(0,0);
+    _labelPrecision->set_justify(Gtk::JUSTIFY_LEFT);
+    _labelPrecision->set_line_wrap(false);
+    _labelPrecision->set_use_markup(false);
+    _labelPrecision->set_selectable(false);
+    _fallbackPrecisionSlider->set_size_request(180,-1);
+    _fallbackPrecisionSlider->set_flags(Gtk::CAN_FOCUS);
+    _fallbackPrecisionSlider->set_update_policy(Gtk::UPDATE_CONTINUOUS);
+    _fallbackPrecisionSlider->set_inverted(false);
+    _fallbackPrecisionSlider->set_digits(1);
+    _fallbackPrecisionSlider->set_draw_value(true);
+    _fallbackPrecisionSlider->set_value_pos(Gtk::POS_TOP);
+    _labelPrecisionComment->set_size_request(90,-1);
+    _labelPrecisionComment->set_alignment(0.5,0.5);
+    _labelPrecisionComment->set_padding(0,0);
+    _labelPrecisionComment->set_justify(Gtk::JUSTIFY_LEFT);
+    _labelPrecisionComment->set_line_wrap(false);
+    _labelPrecisionComment->set_use_markup(false);
+    _labelPrecisionComment->set_selectable(false);
+    hbox6->pack_start(*_fallbackPrecisionSlider, Gtk::PACK_SHRINK, 4);
+    hbox6->pack_start(*_labelPrecisionComment, Gtk::PACK_SHRINK, 4);
+    _labelText->set_alignment(0.5,0.5);
+    _labelText->set_padding(0,0);
+    _labelText->set_justify(Gtk::JUSTIFY_LEFT);
+    _labelText->set_line_wrap(false);
+    _labelText->set_use_markup(false);
+    _labelText->set_selectable(false);
+    hbox5->pack_start(*_labelText, Gtk::PACK_SHRINK, 0);
+    hbox5->pack_start(*_textHandlingCombo, Gtk::PACK_SHRINK, 0);
+    _embedImagesCheck->set_flags(Gtk::CAN_FOCUS);
+    _embedImagesCheck->set_relief(Gtk::RELIEF_NORMAL);
+    _embedImagesCheck->set_mode(true);
+    _embedImagesCheck->set_active(true);
+    vbox3->pack_start(*_labelPrecision, Gtk::PACK_SHRINK, 4);
+    vbox3->pack_start(*hbox6, Gtk::PACK_SHRINK, 0);
+    vbox3->pack_start(*hbox5);
+    vbox3->pack_start(*_embedImagesCheck, Gtk::PACK_SHRINK, 0);
+    alignment4->add(*vbox3);
+    _labelImportSettings->set_alignment(0.5,0.5);
+    _labelImportSettings->set_padding(0,0);
+    _labelImportSettings->set_justify(Gtk::JUSTIFY_LEFT);
+    _labelImportSettings->set_line_wrap(false);
+    _labelImportSettings->set_use_markup(true);
+    _labelImportSettings->set_selectable(false);
+    _importSettingsFrame->set_border_width(4);
+    _importSettingsFrame->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
+    _importSettingsFrame->set_label_align(0,0.5);
+    _importSettingsFrame->add(*alignment4);
+    _importSettingsFrame->set_label_widget(*_labelImportSettings);
+    vbox1->pack_start(*_pageSettingsFrame, Gtk::PACK_EXPAND_PADDING, 0);
+    vbox1->pack_start(*_importSettingsFrame, Gtk::PACK_EXPAND_PADDING, 0);
+    hbox1->pack_start(*vbox1);
+    hbox1->pack_start(*_previewArea, Gtk::PACK_EXPAND_WIDGET, 4);
+    this->get_vbox()->set_homogeneous(false);
+    this->get_vbox()->set_spacing(0);
+    this->get_vbox()->pack_start(*hbox1);
+    this->set_title(_("PDF Import Settings"));
+    this->set_modal(true);
+    this->property_window_position().set_value(Gtk::WIN_POS_NONE);
+    this->set_resizable(true);
+    this->property_destroy_with_parent().set_value(false);
+    this->set_has_separator(true);
+    this->add_action_widget(*cancelbutton, -6);
+    this->add_action_widget(*okbutton, -5);
+    cancelbutton->show();
+    okbutton->show();
+    _labelSelect->show();
+    _pageNumberSpin->show();
+    hbox2->show();
+    _cropCheck->show();
+    _cropTypeCombo->show();
+    hbox3->show();
+    vbox2->show();
+    alignment3->show();
+    _labelPageSettings->show();
+    _pageSettingsFrame->show();
+    _labelPrecision->show();
+    _fallbackPrecisionSlider->show();
+    _labelPrecisionComment->show();
+    hbox6->show();
+    _labelText->show();
+    _textHandlingCombo->show();
+    hbox5->show();
+    _embedImagesCheck->show();
+    vbox3->show();
+    alignment4->show();
+    _labelImportSettings->show();
+    _importSettingsFrame->show();
+    vbox1->show();
+    _previewArea->show();
+    hbox1->show();
+
+    // Connect signals
+    _previewArea->signal_expose_event().connect(sigc::mem_fun(*this, &PdfImportDialog::_onExposePreview));
+    _pageNumberSpin_adj->signal_value_changed().connect(sigc::mem_fun(*this, &PdfImportDialog::_onPageNumberChanged));
+    _cropCheck->signal_toggled().connect(sigc::mem_fun(*this, &PdfImportDialog::_onToggleCropping));
+    _fallbackPrecisionSlider_adj->signal_value_changed().connect(sigc::mem_fun(*this, &PdfImportDialog::_onPrecisionChanged));
+
+    // Create an OutputDev
+    _preview_output_dev = new CairoOutputDev();
+    _preview_output_dev->startDoc(_pdf_doc->getXRef());
+
+    // Set default preview size
+    _preview_width = 200;
+    _preview_height = 300;
+
+    // Init preview
+    _thumb_data = NULL;
+    _cairo_surface = NULL;
+    _pageNumberSpin_adj->set_value(1.0);
+}
+
+PdfImportDialog::~PdfImportDialog() {
+    if (_preview_output_dev) {
+        delete _preview_output_dev;
+    }
+    if (_cairo_surface) {
+        cairo_surface_destroy(_cairo_surface);
+    }
+    if (_thumb_data) {
+        delete _thumb_data;
+    }
+}
+
+bool PdfImportDialog::showDialog() {
+    show();
+    gint b = run();
+    hide();
+    if ( b == Gtk::RESPONSE_OK ) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+int PdfImportDialog::getSelectedPage() {
+    return _current_page;
+}
+
+/**
+ * \brief Retrieves the current settings into a repr which SvgBuilder will use
+ *        for determining the behaviour desired by the user
+ */
+void PdfImportDialog::getImportSettings(Inkscape::XML::Node *prefs) {
+    sp_repr_set_svg_double(prefs, "selectedPage", (double)_current_page);
+    if (_cropCheck->get_active()) {
+        Glib::ustring current_choice = _cropTypeCombo->get_active_text();
+        int num_crop_choices = sizeof(crop_setting_choices) / sizeof(crop_setting_choices[0]);
+        int i = 0;
+        for ( ; i < num_crop_choices ; i++ ) {
+            if ( current_choice == crop_setting_choices[i] ) {
+                break;
+            }
+        }
+        sp_repr_set_svg_double(prefs, "cropTo", (double)i);
+    } else {
+        sp_repr_set_svg_double(prefs, "cropTo", -1.0);
+    }
+    sp_repr_set_svg_double(prefs, "approximationPrecision",
+                           _fallbackPrecisionSlider->get_value());
+    if (_embedImagesCheck->get_active()) {
+        prefs->setAttribute("embedImages", "1");
+    } else {
+        prefs->setAttribute("embedImages", "0");
+    }
+}
+
+/**
+ * \brief Redisplay the comment on the current approximation precision setting
+ * Evenly divides the interval of possible values between the available labels.
+ */
+void PdfImportDialog::_onPrecisionChanged() {
+
+    static Glib::ustring precision_comments[] = {
+        Glib::ustring(_("rough")),
+        Glib::ustring(_("medium")),
+        Glib::ustring(_("fine")),
+        Glib::ustring(_("very fine"))
+    };
+
+    double min = _fallbackPrecisionSlider_adj->get_lower();
+    double max = _fallbackPrecisionSlider_adj->get_upper();
+    int num_intervals = sizeof(precision_comments) / sizeof(precision_comments[0]);
+    double interval_len = ( max - min ) / (double)num_intervals;
+    double value = _fallbackPrecisionSlider_adj->get_value();
+    int comment_idx = (int)floor( ( value - min ) / interval_len );
+    _labelPrecisionComment->set_label(precision_comments[comment_idx]);
+}
+
+void PdfImportDialog::_onToggleCropping() {
+    _cropTypeCombo->set_sensitive(_cropCheck->get_active());
+}
+
+void PdfImportDialog::_onPageNumberChanged() {
+    int page = _pageNumberSpin->get_value_as_int();
+    _current_page = CLAMP(page, 1, _pdf_doc->getCatalog()->getNumPages());
+    _setPreviewPage(_current_page);
+}
+
+/**
+ * \brief Copies image data from a Cairo surface to a pixbuf
+ *
+ * Borrowed from libpoppler, from the file poppler-page.cc
+ * Copyright (C) 2005, Red Hat, Inc.
+ *
+ */
+static void copy_cairo_surface_to_pixbuf (cairo_surface_t *surface,
+                                          unsigned char   *data,
+                                          GdkPixbuf       *pixbuf)
+{
+    int cairo_width, cairo_height, cairo_rowstride;
+    unsigned char *pixbuf_data, *dst, *cairo_data;
+    int pixbuf_rowstride, pixbuf_n_channels;
+    unsigned int *src;
+    int x, y;
+
+    cairo_width = cairo_image_surface_get_width (surface);
+    cairo_height = cairo_image_surface_get_height (surface);
+    cairo_rowstride = cairo_width * 4;
+    cairo_data = data;
+
+    pixbuf_data = gdk_pixbuf_get_pixels (pixbuf);
+    pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+    pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+    if (cairo_width > gdk_pixbuf_get_width (pixbuf))
+        cairo_width = gdk_pixbuf_get_width (pixbuf);
+    if (cairo_height > gdk_pixbuf_get_height (pixbuf))
+        cairo_height = gdk_pixbuf_get_height (pixbuf);
+    for (y = 0; y < cairo_height; y++)
+    {
+        src = (unsigned int *) (cairo_data + y * cairo_rowstride);
+        dst = pixbuf_data + y * pixbuf_rowstride;
+        for (x = 0; x < cairo_width; x++)
+        {
+            dst[0] = (*src >> 16) & 0xff;
+            dst[1] = (*src >> 8) & 0xff;
+            dst[2] = (*src >> 0) & 0xff;
+            if (pixbuf_n_channels == 4)
+                dst[3] = (*src >> 24) & 0xff;
+            dst += pixbuf_n_channels;
+            src++;
+        }
+    }
+}
+
+/**
+ * \brief Updates the preview area with the previously rendered thumbnail
+ */
+bool PdfImportDialog::_onExposePreview(GdkEventExpose *event) {
+
+    Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true,
+            8, _thumb_width, _thumb_height);
+    // Set background to white
+    thumb->fill(0xffffffff);
+    Glib::RefPtr<Gdk::Pixmap> back_pixmap = Gdk::Pixmap::create(_previewArea->get_window(),
+            _thumb_width, _thumb_height, -1);
+    back_pixmap->draw_pixbuf(Glib::RefPtr<Gdk::GC>(), thumb, 0, 0, 0, 0,
+                             static_cast<int>(_thumb_width),
+                             static_cast<int>(_thumb_height),
+                             Gdk::RGB_DITHER_NONE, 0, 0);
+    _previewArea->get_window()->set_back_pixmap(back_pixmap, false);
+    _previewArea->get_window()->clear();
+    // Copy the thumbnail image from the Cairo surface
+    copy_cairo_surface_to_pixbuf(_cairo_surface, _thumb_data, thumb->gobj());
+    _previewArea->get_window()->draw_pixbuf(Glib::RefPtr<Gdk::GC>(), thumb,
+                                            0, 0, 0, 0, -1, -1,
+                                            Gdk::RGB_DITHER_NONE, 0, 0);
+
+    return true;
+}
+
+/**
+ * \brief Renders the given page's thumbnail using Cairo
+ */
+void PdfImportDialog::_setPreviewPage(int page) {
+
+    _previewed_page = _pdf_doc->getCatalog()->getPage(page);
+    // TODO: When available, obtain the thumbnail from the PDF document itself
+    // Get page size by accounting for rotation
+    double width, height;
+    int rotate = _previewed_page->getRotate();
+    if ( rotate == 90 || rotate == 270 ) {
+        height = _previewed_page->getCropWidth();
+        width = _previewed_page->getCropHeight();
+    } else {
+        width = _previewed_page->getCropWidth();
+        height = _previewed_page->getCropHeight();
+    }
+    // Calculate the needed scaling for the page
+    double scale_x = (double)_preview_width / width;
+    double scale_y = (double)_preview_height / height;
+    double scale_factor = ( scale_x > scale_y ) ? scale_y : scale_x;
+    // Create new Cairo surface
+    _thumb_width = (int)ceil( width * scale_factor );
+    _thumb_height = (int)ceil( height * scale_factor );
+    int rowstride = _thumb_width * 4;
+    if (_thumb_data) {
+        delete _thumb_data;
+    }
+    _thumb_data = new unsigned char[ rowstride * _thumb_height ];
+    if (_cairo_surface) {
+        cairo_surface_destroy(_cairo_surface);
+    }
+    _cairo_surface = cairo_image_surface_create_for_data(_thumb_data,
+            CAIRO_FORMAT_ARGB32, _thumb_width, _thumb_height, rowstride);
+    cairo_t *cr = cairo_create(_cairo_surface);
+    cairo_scale(cr, scale_factor, scale_factor);    // Use Cairo for resizing the image
+    _preview_output_dev->setCairo(cr);
+    // Render page
+    _previewed_page->displaySlice(_preview_output_dev,
+                       72.0, 72.0, 0,
+                       FALSE, /* useMediaBox */
+                       TRUE, /* crop */
+                       0, 0,
+                       (int)ceil(_previewed_page->getCropWidth()),
+                       (int)ceil(_previewed_page->getCropHeight()),
+                       FALSE, /* printing */
+                       _pdf_doc->getCatalog());
+    // Clean up
+    _preview_output_dev->setCairo(NULL);
+    cairo_destroy(cr);
+    // Redraw preview area
+    _previewArea->set_size_request(_preview_width, _preview_height);
+    _previewArea->queue_draw();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Parses the selected page of the given PDF document using PdfParser.
  */
 SPDocument *
 PdfInput::open(::Inkscape::Extension::Input * mod, const gchar * uri) {
@@ -58,9 +497,16 @@ PdfInput::open(::Inkscape::Extension::Input * mod, const gchar * uri) {
  
         return NULL;
     }
+    PdfImportDialog *dlg = new PdfImportDialog(pdf_doc);
+    if (!dlg->showDialog()) {
+        delete dlg;
+        delete pdf_doc;
+
+        return NULL;
+    }
 
     // Get needed page
-    int page_num = 1;
+    int page_num = dlg->getSelectedPage();
     Catalog *catalog = pdf_doc->getCatalog();
     Page *page = catalog->getPage(page_num);
 
@@ -68,16 +514,61 @@ PdfInput::open(::Inkscape::Extension::Input * mod, const gchar * uri) {
     bool saved = sp_document_get_undo_sensitive(doc);
     sp_document_set_undo_sensitive(doc, false); // No need to undo in this temporary document
 
-    // Create builder and parser
+    // Create builder
     gchar *docname = g_path_get_basename(uri);
     gchar *dot = g_strrstr(docname, ".");
     if (dot) {
         *dot = 0;
     }
     SvgBuilder *builder = new SvgBuilder(doc, docname, pdf_doc->getXRef());
+
+    // Get preferences
+    Inkscape::XML::Node *prefs = builder->getPreferences();
+    dlg->getImportSettings(prefs);
+
+    // Apply crop settings
+    PDFRectangle *clipToBox = NULL;
+    double crop_setting;
+    sp_repr_get_double(prefs, "cropTo", &crop_setting);
+    if ( crop_setting >= 0.0 ) {    // Do page clipping
+        int crop_choice = (int)crop_setting;
+        switch (crop_choice) {
+            case 0: // Media box
+                clipToBox = page->getMediaBox();
+                break;
+            case 1: // Crop box
+                clipToBox = page->getCropBox();
+                break;
+            case 2: // Bleed box
+                clipToBox = page->getBleedBox();
+                break;
+            case 3: // Trim box
+                clipToBox = page->getTrimBox();
+                break;
+            case 4: // Art box
+                clipToBox = page->getArtBox();
+                break;
+            default:
+                break;
+        }
+    }
+
+    // Create parser
     PdfParser *pdf_parser = new PdfParser(pdf_doc->getXRef(), builder, page_num-1, page->getRotate(),
-                                          page->getResourceDict(), page->getCropBox());
+                                          page->getResourceDict(), page->getCropBox(), clipToBox);
 
+    // Set up approximation precision for parser
+    double color_delta;
+    sp_repr_get_double(prefs, "approximationPrecision", &color_delta);
+    if ( color_delta <= 0.0 ) {
+        color_delta = 1.0 / 2.0;
+    } else {
+        color_delta = 1.0 / color_delta;
+    }
+    for ( int i = 1 ; i <= pdfNumShadingTypes ; i++ ) {
+        pdf_parser->setApproximationPrecision(i, color_delta, 6);
+    }
+    
     // Parse the document structure
     Object obj;
     page->getContents(&obj);
index abbfc838e657a0bfc1e907bddc9cb42f7d54bbe8..b7d3de774a600f9ef58498177a6e8735a3dab8bf 100644 (file)
 
 #include "../../implementation/implementation.h"
 
+#include <gtkmm/dialog.h>
+#include <gtkmm/button.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/label.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/box.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/drawingarea.h>
+#include <gtkmm/alignment.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/scale.h>
+#include <glibmm/i18n.h>
+#include <gdk/gdk.h>
+
+#include "PDFDoc.h"
+#include "CairoOutputDev.h"
+
 namespace Inkscape {
 namespace Extension {
 namespace Internal {
 
+class PdfImportDialog : public Gtk::Dialog
+{
+public:
+    PdfImportDialog(PDFDoc *doc);
+    virtual ~PdfImportDialog();
+
+    bool showDialog();
+    int getSelectedPage();
+    void getImportSettings(Inkscape::XML::Node *prefs);
+
+private:
+    void _setPreviewPage(int page);
+
+    // Signal handlers
+    bool _onExposePreview(GdkEventExpose *event);
+    void _onPageNumberChanged();
+    void _onToggleCropping();
+    void _onPrecisionChanged();
+
+    class Gtk::Button * cancelbutton;
+    class Gtk::Button * okbutton;
+    class Gtk::Label * _labelSelect;
+    class Gtk::SpinButton * _pageNumberSpin;
+    class Gtk::HBox * hbox2;
+    class Gtk::CheckButton * _cropCheck;
+    class Gtk::ComboBoxText * _cropTypeCombo;
+    class Gtk::HBox * hbox3;
+    class Gtk::VBox * vbox2;
+    class Gtk::Alignment * alignment3;
+    class Gtk::Label * _labelPageSettings;
+    class Gtk::Frame * _pageSettingsFrame;
+    class Gtk::Label * _labelPrecision;
+    class Gtk::HScale * _fallbackPrecisionSlider;
+    class Gtk::Adjustment *_fallbackPrecisionSlider_adj;
+    class Gtk::Label * _labelPrecisionComment;
+    class Gtk::HBox * hbox6;
+    class Gtk::Label * _labelText;
+    class Gtk::ComboBoxText * _textHandlingCombo;
+    class Gtk::HBox * hbox5;
+    class Gtk::CheckButton * _embedImagesCheck;
+    class Gtk::VBox * vbox3;
+    class Gtk::Alignment * alignment4;
+    class Gtk::Label * _labelImportSettings;
+    class Gtk::Frame * _importSettingsFrame;
+    class Gtk::VBox * vbox1;
+    class Gtk::DrawingArea * _previewArea;
+    class Gtk::HBox * hbox1;
+
+    PDFDoc *_pdf_doc;   // Document to be imported
+    int _current_page;  // Current selected page
+    Page *_previewed_page;    // Currently previewed page
+    unsigned char *_thumb_data; // Thumbnail image data
+    int _thumb_width, _thumb_height;    // Thumbnail size
+    int _preview_width, _preview_height;    // Size of the preview area
+    cairo_surface_t *_cairo_surface;
+    CairoOutputDev *_preview_output_dev;
+};
+
+    
 class PdfInput: public Inkscape::Extension::Implementation::Implementation {
     PdfInput () { };
 public:
index 14f9c610280b5b911a9ff53be29ce58a05c41b5c..7f801d4b44bd6aed0af06a53f87c21a221307c91 100644 (file)
@@ -84,6 +84,10 @@ SvgBuilder::SvgBuilder(SPDocument *document, gchar *docname, XRef *xref) {
     _container = _root = _doc->rroot;
     _root->setAttribute("xml:space", "preserve");
     _init();
+
+    // Set default preference settings
+    _preferences = _xml_doc->createElement("svgbuilder:prefs");
+    _preferences->setAttribute("embedImages", "1");
 }
 
 SvgBuilder::SvgBuilder(SvgBuilder *parent, Inkscape::XML::Node *root) {
@@ -92,6 +96,7 @@ SvgBuilder::SvgBuilder(SvgBuilder *parent, Inkscape::XML::Node *root) {
     _docname = parent->_docname;
     _xref = parent->_xref;
     _xml_doc = parent->_xml_doc;
+    _preferences = parent->_preferences;
     _container = this->_root = root;
     _init();
 }
@@ -1329,13 +1334,15 @@ Inkscape::XML::Node *SvgBuilder::_createImage(Stream *str, int width, int height
         png_destroy_write_struct(&png_ptr, &info_ptr);
         return NULL;
     }
-
+    // Decide whether we should embed this image
+    double attr_value = 1.0;
+    sp_repr_get_double(_preferences, "embedImages", &attr_value);
+    bool embed_image = ( attr_value != 0.0 );
     // Set read/write functions
     Inkscape::IO::StringOutputStream base64_string;
     Inkscape::IO::Base64OutputStream base64_stream(base64_string);
     FILE *fp;
     gchar *file_name;
-    bool embed_image = true;
     if (embed_image) {
         base64_stream.setColumnWidth(0);   // Disable line breaks
         png_set_write_fn(png_ptr, &base64_stream, png_write_base64stream, png_flush_base64stream);
index 9298884a1898fddfddfb91d317be1269f345dabe..96525ba2bb2389efafa23d1f5ff5003061622ea4 100644 (file)
@@ -103,6 +103,9 @@ public:
     void setDocumentSize(double width, double height);  // Document size in px
     void setAsLayer(char *layer_name=NULL);
     void setGroupOpacity(double opacity);
+    Inkscape::XML::Node *getPreferences() {
+        return _preferences;
+    }
 
     // Handling the node stack
     Inkscape::XML::Node *pushGroup();
@@ -220,6 +223,7 @@ private:
     Inkscape::XML::Document *_xml_doc;
     Inkscape::XML::Node *_root;  // Root node from the point of view of this SvgBuilder
     Inkscape::XML::Node *_container; // Current container (group/pattern/mask)
+    Inkscape::XML::Node *_preferences;  // Preferences container node
     double _width, _height;       // Document size in px
 };