=== modified file 'src/file-update.cpp' --- src/file-update.cpp 2017-02-02 01:55:39 +0000 +++ src/file-update.cpp 2017-02-04 12:54:56 +0000 @@ -8,21 +8,51 @@ * Marc Jeanmougin * su_v */ +#include "extension/effect.h" +#include "extension/db.h" +#include "extension/input.h" +#include "extension/output.h" +#include "extension/system.h" + +#include "inkscape.h" #include "file.h" +#include "preferences.h" #include "sp-root.h" #include "sp-text.h" #include "sp-tspan.h" #include "sp-flowdiv.h" #include "sp-flowtext.h" #include "sp-object.h" +#include "sp-defs.h" #include "sp-item.h" +#include "dir-util.h" #include "style.h" #include "document.h" +#include "document-undo.h" #include #include "text-editing.h" +#include "document-undo.h" +#include "display/canvas-grid.h" +#include "sp-guide.h" +#include "selection-chemistry.h" +#include "persp3d.h" +#include "proj_pt.h" +#include "ui/shape-editor.h" +#include "io/sys.h" +#include "print.h" +#include "ui/interface.h" +#include "desktop.h" +#include "message.h" +#include "message-stack.h" +#include "verbs.h" +#include "sp-namedview.h" +#include +using Inkscape::DocumentUndo; using namespace std; +int sp_file_convert_dpi_method_commandline = -1; // Unset + bool is_line(SPObject *i) { if (!(i->getAttribute("sodipodi:role"))) @@ -161,6 +191,380 @@ sp_file_text_run_recursive(fix_update, doc->getRoot()); } +// Quick and dirty internal backup function +bool sp_file_save_backup( Glib::ustring uri ) { + Glib::ustring out = uri; + out.insert(out.find(".svg"),"_backup"); + + FILE *filein = Inkscape::IO::fopen_utf8name(uri.c_str(), "rb"); + if (!filein) { + std::cerr << "sp_file_save_backup: failed to open: " << uri << std::endl; + return false; + } + + FILE *fileout = Inkscape::IO::fopen_utf8name(out.c_str(), "wb"); + if (!fileout) { + std::cerr << "sp_file_save_backup: failed to open: " << out << std::endl; + fclose(filein); + return false; + } + + int ch; + while ((ch = fgetc(filein)) != EOF) { + fputc(ch, fileout); + } + fflush(fileout); + + bool return_value = true; + if (ferror(fileout)) { + std::cerr << "sp_file_save_backup: error when writing to: " << out << std::endl; + return_value = false; + } + + fclose(filein); + fclose(fileout); + + return return_value; +} + +void sp_file_convert_dpi(SPDocument *doc) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring uri = doc->getURI(); + SPRoot *root = doc->getRoot(); + + // See if we need to offer the user a fix for the 90->96 px per inch change. + // std::cout << "SPFileOpen:" << std::endl; + // std::cout << " Version: " << sp_version_to_string(root->version.inkscape) << std::endl; + // std::cout << " SVG file from old Inkscape version detected: " + // << sp_version_to_string(root->version.inkscape) << std::endl; + static const double ratio = 90.0/96.0; + + bool need_fix_viewbox = false; + bool need_fix_units = false; + bool need_fix_guides = false; + bool need_fix_grid_mm = false; + bool need_fix_box3d = false; + bool did_scaling = false; + + // Check if potentially need viewbox or unit fix + switch (root->width.unit) { + case SP_CSS_UNIT_PC: + case SP_CSS_UNIT_PT: + case SP_CSS_UNIT_MM: + case SP_CSS_UNIT_CM: + case SP_CSS_UNIT_IN: + need_fix_viewbox = true; + break; + case SP_CSS_UNIT_NONE: + case SP_CSS_UNIT_PX: + need_fix_units = true; + break; + case SP_CSS_UNIT_EM: + case SP_CSS_UNIT_EX: + case SP_CSS_UNIT_PERCENT: + // OK + break; + default: + std::cerr << "sp_file_open: Unhandled width unit!" << std::endl; + } + + switch (root->height.unit) { + case SP_CSS_UNIT_PC: + case SP_CSS_UNIT_PT: + case SP_CSS_UNIT_MM: + case SP_CSS_UNIT_CM: + case SP_CSS_UNIT_IN: + need_fix_viewbox = true; + break; + case SP_CSS_UNIT_NONE: + case SP_CSS_UNIT_PX: + need_fix_units = true; + break; + case SP_CSS_UNIT_EM: + case SP_CSS_UNIT_EX: + case SP_CSS_UNIT_PERCENT: + // OK + break; + default: + std::cerr << "sp_file_open: Unhandled height unit!" << std::endl; + } + + if (need_fix_units && need_fix_viewbox) { + std::cerr << "Different units in document size !" << std::endl; + if (root->viewBox_set) + need_fix_viewbox = false; + else + need_fix_units = false; + } + + // std::cout << "Absolute SVG units in root? " << (need_fix_viewbox?"true":"false") << std::endl; + // std::cout << "User units in root? " << (need_fix_units ?"true":"false") << std::endl; + + if ((!root->viewBox_set && need_fix_viewbox) || need_fix_units) { + int response = FILE_DPI_UNCHANGED; // default + + /******** UI *******/ + bool backup = prefs->getBool("/options/dpifixbackup", true); + if (INKSCAPE.use_gui() && sp_file_convert_dpi_method_commandline == -1) { + Gtk::Dialog scale_dialog(_("Convert legacy Inkscape file")); + scale_dialog.set_border_width(10); + scale_dialog.set_resizable(false); + Gtk::Label explanation; + explanation.set_markup(Glib::ustring("") + doc->getName() + "\n" + + _("was created in an older version of Inkscape (90 DPI) and we need " + "to make it compatible with newer versions (96 DPI). Tell us about this file:\n")); + explanation.set_line_wrap(true); + explanation.set_size_request(600,-1); + Gtk::RadioButton::Group c1, c2; + + Gtk::Label choice1_label; + choice1_label.set_markup( + _("This file contains digital artwork for screen display. (Choose if unsure.)")); + Gtk::RadioButton choice1(c1); + choice1.add(choice1_label); + Gtk::RadioButton choice2(c1, _("This file is intended for physical output, such as paper or 3D prints.")); + Gtk::Label choice2_1_label; + choice2_1_label.set_markup(_("The appearance of elements such as clips, masks, filters, and clones\n" + "is most important. (Choose if unsure.)")); + Gtk::RadioButton choice2_1(c2); + choice2_1.add(choice2_1_label); + Gtk::RadioButton choice2_2(c2, _("The accuracy of the physical unit size and position values of objects\n" + "in the file is most important. (Experimental.)")); + Gtk::CheckButton backup_button(_("Create a backup file in same directory.")); + Gtk::Expander moreinfo(_("More details...")); + Gtk::Label moreinfo_text; + moreinfo_text.set_markup( + _("We've updated Inkscape to follow the CSS standard of 96 DPI for better browser " + "compatibility; we used to use 90 DPI. " + "Digital artwork for screen display will be converted to 96 DPI without scaling and should be " + "unaffected. " + "Artwork drawn at 90 DPI for a specific physical size will be too small if converted to 96 DPI " + "without any scaling. There are two scaling methods:\n\n" + "Scaling the whole document: The least error-prone method, this preserves the appearance of " + "the artwork, including filters and the position of masks, etc. " + "The scale of the artwork relative to the document size may not be accurate.\n\n" + "Scaling individual elements in the artwork: This method is less reliable and can result in " + "a changed appearance, " + "but is better for physical output that relies on accurate sizes and positions (for example, for " + "3D printing.)\n\n" + "More information about this change are available in the Inkscape FAQ" + "")); + moreinfo_text.set_line_wrap(true); + moreinfo_text.set_size_request(554,-1); +#if WITH_GTKMM_3_0 + Gtk::Box b; +#else + Gtk::VBox b; +#endif + b.set_border_width(0); + + b.pack_start(choice2_1, false, false, 4); + b.pack_start(choice2_2, false, false, 4); + choice2_1.show(); + choice2_2.show(); + + Gtk::Alignment balign(0, 0, 0, 0); + balign.set_padding (0, 0, 30, 0); + balign.show(); + balign.add(b); +#if WITH_GTKMM_3_0 + Gtk::Box *content = scale_dialog.get_content_area(); +#else + Gtk::VBox *content = scale_dialog.get_vbox(); +#endif + content->pack_start(explanation, false, false, 5); + content->pack_start(choice1, false, false, 5); + content->pack_start(choice2, false, false, 5); + content->pack_start(balign, false, false, 5); + content->pack_start(backup_button, false, false, 5); + Gtk::Button *ok_button = scale_dialog.add_button(_("OK"), GTK_RESPONSE_ACCEPT); + backup_button.set_active(backup); + content->pack_start(moreinfo, false, false, 5); + moreinfo.add(moreinfo_text); + scale_dialog.show_all_children(); + b.hide(); +#if WITH_GTKMM_3_0 + choice1.signal_clicked().connect(sigc::mem_fun(b, &Gtk::Box::hide)); + choice2.signal_clicked().connect(sigc::mem_fun(b, &Gtk::Box::show)); +#else + choice1.signal_clicked().connect(sigc::mem_fun(b, &Gtk::VBox::hide)); + choice2.signal_clicked().connect(sigc::mem_fun(b, &Gtk::VBox::show)); +#endif + + response = prefs->getInt("/options/dpiupdatemethod", FILE_DPI_UNCHANGED); + if ( response != FILE_DPI_UNCHANGED ) { + choice2.set_active(); + b.show(); + if ( response == FILE_DPI_DOCUMENT_SCALED) + choice2_2.set_active(); + } + ok_button->grab_focus(); + + int status = scale_dialog.run(); + if ( status == GTK_RESPONSE_ACCEPT ) { + backup = backup_button.get_active(); + prefs->setBool("/options/dpifixbackup", backup); + response = choice1.get_active() ? FILE_DPI_UNCHANGED : choice2_1.get_active() ? FILE_DPI_VIEWBOX_SCALED : FILE_DPI_DOCUMENT_SCALED; + prefs->setInt("/options/dpiupdatemethod", response); + } else if (sp_file_convert_dpi_method_commandline != -1) { + response = sp_file_convert_dpi_method_commandline; + } else { + response = FILE_DPI_UNCHANGED; + } + } else { // GUI with explicit option + response = FILE_DPI_UNCHANGED; + } + + if (backup && (response != FILE_DPI_UNCHANGED)) { + sp_file_save_backup(uri); + } + + if (!(response == FILE_DPI_UNCHANGED && need_fix_units)) { + need_fix_guides = true; // Only fix guides if drawing scaled + need_fix_box3d = true; + } + + if (response == FILE_DPI_VIEWBOX_SCALED) { + double ratio_viewbox = need_fix_units ? 1.0 : ratio; + + doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value("px") * ratio_viewbox, + doc->getHeight().value("px") * ratio_viewbox)); + Inkscape::Util::Quantity width = // maybe set it to mm ? + Inkscape::Util::Quantity(doc->getWidth().value("px") / ratio, "px"); + Inkscape::Util::Quantity height = Inkscape::Util::Quantity(doc->getHeight().value("px") / ratio, "px"); + if (need_fix_units) + doc->setWidthAndHeight(width, height, false); + + } else if (response == FILE_DPI_DOCUMENT_SCALED) { + + Inkscape::Util::Quantity width = // maybe set it to mm ? + Inkscape::Util::Quantity(doc->getWidth().value("px") / ratio, "px"); + Inkscape::Util::Quantity height = Inkscape::Util::Quantity(doc->getHeight().value("px") / ratio, "px"); + if (need_fix_units) + doc->setWidthAndHeight(width, height, false); + + if (!root->viewBox_set) { + // Save preferences + bool transform_stroke = prefs->getBool("/options/transform/stroke", true); + bool transform_rectcorners = prefs->getBool("/options/transform/rectcorners", true); + bool transform_pattern = prefs->getBool("/options/transform/pattern", true); + bool transform_gradient = prefs->getBool("/options/transform/gradient", true); + + prefs->setBool("/options/transform/stroke", true); + prefs->setBool("/options/transform/rectcorners", true); + prefs->setBool("/options/transform/pattern", true); + prefs->setBool("/options/transform/gradient", true); + + Inkscape::UI::ShapeEditor::blockSetItem(true); + doc->getRoot()->scaleChildItemsRec(Geom::Scale(1 / ratio), Geom::Point(0, 0), false); + Inkscape::UI::ShapeEditor::blockSetItem(false); + + // Restore preferences + prefs->setBool("/options/transform/stroke", transform_stroke); + prefs->setBool("/options/transform/rectcorners", transform_rectcorners); + prefs->setBool("/options/transform/pattern", transform_pattern); + prefs->setBool("/options/transform/gradient", transform_gradient); + + did_scaling = true; + } + } else { // FILE_DPI_UNCHANGED + if (need_fix_units) + need_fix_grid_mm = true; + } + } + + // Fix guides and grids and perspective + for (SPObject *child = root->firstChild(); child; child = child->getNext()) { + SPNamedView *nv = dynamic_cast(child); + if (nv) { + if (need_fix_guides) { + // std::cout << "Fixing guides" << std::endl; + for (SPObject *child2 = nv->firstChild(); child2; child2 = child2->getNext()) { + SPGuide *gd = dynamic_cast(child2); + if (gd) { + gd->moveto(gd->getPoint() / ratio, true); + } + } + } + + for (std::vector::const_iterator it = nv->grids.begin(); it != nv->grids.end(); + ++it) { + Inkscape::CanvasXYGrid *xy = dynamic_cast(*it); + if (xy) { + // std::cout << "A grid: " << xy->getSVGName() << std::endl; + // std::cout << " Origin: " << xy->origin + // << " Spacing: " << xy->spacing << std::endl; + // std::cout << (xy->isLegacy()?" Legacy":" Not Legacy") << std::endl; + Geom::Scale scale = doc->getDocumentScale(); + if (xy->isLegacy()) { + if (xy->isPixel()) { + if (need_fix_grid_mm) { + xy->Scale(Geom::Scale(1, 1)); // See note below + } else { + scale *= Geom::Scale(ratio, ratio); + xy->Scale(scale.inverse()); /* *** */ + } + } else { + if (need_fix_grid_mm) { + xy->Scale(Geom::Scale(ratio, ratio)); + } else { + xy->Scale(scale.inverse()); /* *** */ + } + } + } else { + if (need_fix_guides) { + if (did_scaling) { + xy->Scale(Geom::Scale(ratio, ratio).inverse()); + } else { + // HACK: Scaling the document does not seem to cause + // grids defined in document units to be updated. + // This forces an update. + xy->Scale(Geom::Scale(1, 1)); + } + } + } + } + } + } // If SPNamedView + + SPDefs *defs = dynamic_cast(child); + if (defs && need_fix_box3d) { + for (SPObject *child = defs->firstChild(); child; child = child->getNext()) { + Persp3D *persp3d = dynamic_cast(child); + if (persp3d) { + std::vector tokens; + + const gchar *vp_x = persp3d->getAttribute("inkscape:vp_x"); + const gchar *vp_y = persp3d->getAttribute("inkscape:vp_y"); + const gchar *vp_z = persp3d->getAttribute("inkscape:vp_z"); + const gchar *vp_o = persp3d->getAttribute("inkscape:persp3d-origin"); + // std::cout << "Found Persp3d: " + // << " vp_x: " << vp_x + // << " vp_y: " << vp_y + // << " vp_z: " << vp_z << std::endl; + Proj::Pt2 pt_x(vp_x); + Proj::Pt2 pt_y(vp_y); + Proj::Pt2 pt_z(vp_z); + Proj::Pt2 pt_o(vp_o); + pt_x = pt_x * (1.0 / ratio); + pt_y = pt_y * (1.0 / ratio); + pt_z = pt_z * (1.0 / ratio); + pt_o = pt_o * (1.0 / ratio); + persp3d->setAttribute("inkscape:vp_x", pt_x.coord_string()); + persp3d->setAttribute("inkscape:vp_y", pt_y.coord_string()); + persp3d->setAttribute("inkscape:vp_z", pt_z.coord_string()); + persp3d->setAttribute("inkscape:persp3d-origin", pt_o.coord_string()); + } + } + } + } // Look for SPNamedView and SPDefs loop + + // desktop->getDocument()->ensureUpToDate(); // Does not update box3d! + DocumentUndo::done(doc, SP_VERB_NONE, _("Update Document")); +} + /* Local Variables: mode:c++ === modified file 'src/file.cpp' --- src/file.cpp 2017-01-22 19:05:28 +0000 +++ src/file.cpp 2017-02-03 20:45:24 +0000 @@ -69,14 +69,6 @@ #include "event-log.h" #include "ui/dialog/font-substitution.h" -// For updating old Inkscape SVG files -#include "display/canvas-grid.h" -#include "sp-guide.h" -#include "selection-chemistry.h" -#include "persp3d.h" -#include "proj_pt.h" -#include "ui/shape-editor.h" - #include using Inkscape::DocumentUndo; @@ -246,43 +238,6 @@ } -// Quick and dirty internal backup function -bool sp_file_save_backup( Glib::ustring uri ) { - - Glib::ustring out = uri; - out.insert(out.find(".svg"),"_backup"); - - FILE *filein = Inkscape::IO::fopen_utf8name(uri.c_str(), "rb"); - if (!filein) { - std::cerr << "sp_file_save_backup: failed to open: " << uri << std::endl; - return false; - } - - FILE *fileout = Inkscape::IO::fopen_utf8name(out.c_str(), "wb"); - if (!fileout) { - std::cerr << "sp_file_save_backup: failed to open: " << out << std::endl; - fclose( filein ); - return false; - } - - int ch; - while ((ch = fgetc(filein)) != EOF) { - fputc(ch, fileout); - } - fflush(fileout); - - bool return_value = true; - if (ferror(fileout)) { - std::cerr << "sp_file_save_backup: error when writing to: " << out << std::endl; - return_value = false; - } - - fclose(filein); - fclose(fileout); - - return return_value; -} - /*###################### ## O P E N ######################*/ @@ -348,381 +303,11 @@ root->original.svg = root->version.svg; if (INKSCAPE.use_gui()) { - - // See if we need to offer the user a fix for the 90->96 px per inch change. - // std::cout << "SPFileOpen:" << std::endl; - // std::cout << " Version: " << sp_version_to_string(root->version.inkscape) << std::endl; - - if ( sp_version_inside_range( root->version.inkscape, 0, 1, 0, 92 ) ) { - - // std::cout << " SVG file from old Inkscape version detected: " - // << sp_version_to_string(root->version.inkscape) << std::endl; - static const double ratio = 90.0/96.0; - - bool need_fix_viewbox = false; - bool need_fix_units = false; - bool need_fix_guides = false; - bool need_fix_grid_mm = false; - bool need_fix_box3d = false; - bool did_scaling = false; - - // Check if potentially need viewbox or unit fix - switch (root->width.unit) { - case SP_CSS_UNIT_PC: - case SP_CSS_UNIT_PT: - case SP_CSS_UNIT_MM: - case SP_CSS_UNIT_CM: - case SP_CSS_UNIT_IN: - need_fix_viewbox = true; - break; - case SP_CSS_UNIT_NONE: - case SP_CSS_UNIT_PX: - need_fix_units = true; - break; - case SP_CSS_UNIT_EM: - case SP_CSS_UNIT_EX: - case SP_CSS_UNIT_PERCENT: - // OK - break; - default: - std::cerr << "sp_file_open: Unhandled width unit!" << std::endl; - } - - switch (root->height.unit) { - case SP_CSS_UNIT_PC: - case SP_CSS_UNIT_PT: - case SP_CSS_UNIT_MM: - case SP_CSS_UNIT_CM: - case SP_CSS_UNIT_IN: - need_fix_viewbox = true; - break; - case SP_CSS_UNIT_NONE: - case SP_CSS_UNIT_PX: - need_fix_units = true; - break; - case SP_CSS_UNIT_EM: - case SP_CSS_UNIT_EX: - case SP_CSS_UNIT_PERCENT: - // OK - break; - default: - std::cerr << "sp_file_open: Unhandled height unit!" << std::endl; - } - - // std::cout << "Absolute SVG units in root? " << (need_fix_viewbox?"true":"false") << std::endl; - // std::cout << "User units in root? " << (need_fix_units ?"true":"false") << std::endl; - - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - if (!root->viewBox_set && need_fix_viewbox) { - - Glib::ustring msg = _( - "Old Inkscape files use 1in == 90px. CSS requires 1in == 96px.\n" - "Drawing elements may be too small. This can be corrected by\n" - "either setting the SVG 'viewBox' to compensate or by scaling\n" - "all the elements in the drawing."); - - Gtk::Dialog scaleDialog( _("Old Inkscape file detected (90 DPI)")); - - Gtk::Label info; - info.set_markup(msg.c_str()); - info.show(); - -#if WITH_GTKMM_3_0 - scaleDialog.get_content_area()->pack_start(info, false, false, 20); -#else - scaleDialog.get_vbox()->pack_start(info, false, false, 20); -#endif - - Gtk::CheckButton backupButton( _("Create backup file (in same directory).") ); - bool backup = prefs->getBool("/options/dpifixbackup", true); - backupButton.set_active( backup ); - backupButton.show(); - -#if WITH_GTKMM_3_0 - scaleDialog.get_content_area()->pack_start(backupButton, false, false, 20); -#else - scaleDialog.get_vbox()->pack_start(backupButton, false, false, 20); -#endif - - scaleDialog.add_button(_("Set 'viewBox'"), 1); - scaleDialog.add_button(_("Scale elements"), 2); - scaleDialog.add_button(_("Ignore"), 3); - - gint response = scaleDialog.run(); - backup = backupButton.get_active(); - prefs->setBool("/options/dpifixbackup", backup); - - if ( backup && response != 3) { - sp_file_save_backup( uri ); - } - - if (response == 1) { - - doc->setViewBox(Geom::Rect::from_xywh( - 0, 0, - doc->getWidth().value("px") * ratio, - doc->getHeight().value("px") * ratio)); - - } else if (response == 2 ) { - - // std::list effects; - // Inkscape::Extension::db.get_effect_list(effects); - // std::list::iterator it = effects.begin(); - // bool did = false; - // while (it != effects.end()) { - // if (strcmp((*it)->get_id(), "org.inkscape.dpi90to96") == 0) { - // Inkscape::UI::View::View *view = desktop; - // (*it)->effect(view); - // did = true; - // break; - // } - // ++it; - // } - // if (!did) { - // std::cerr << "sp_file_open: Failed to find dpi90to96 extension." << std::endl; - // } - - // Save preferences - bool transform_stroke = prefs->getBool("/options/transform/stroke", true); - bool transform_rectcorners = prefs->getBool("/options/transform/rectcorners", true); - bool transform_pattern = prefs->getBool("/options/transform/pattern", true); - bool transform_gradient = prefs->getBool("/options/transform/gradient", true); - - prefs->setBool("/options/transform/stroke", true); - prefs->setBool("/options/transform/rectcorners", true); - prefs->setBool("/options/transform/pattern", true); - prefs->setBool("/options/transform/gradient", true); - - Inkscape::UI::ShapeEditor::blockSetItem(true); - doc->getRoot()->scaleChildItemsRec(Geom::Scale(1/ratio),Geom::Point(0, 0), false); - Inkscape::UI::ShapeEditor::blockSetItem(false); - - // Restore preferences - prefs->setBool("/options/transform/stroke", transform_stroke); - prefs->setBool("/options/transform/rectcorners", transform_rectcorners); - prefs->setBool("/options/transform/pattern", transform_pattern); - prefs->setBool("/options/transform/gradient", transform_gradient); - - did_scaling = true; - } - - need_fix_box3d = true; - need_fix_guides = true; // Always fix guides - } - - else if (need_fix_units) { - - Glib::ustring msg = _( - "Old Inkscape files use 1in == 90px. CSS requires 1in == 96px.\n" - "Drawings meant to match a physical size (e.g. Letter or A4)\n" - "will be too small. Scaling the drawing can correct for this.\n" - "Internal scaling can be handled either by setting the SVG 'viewBox'\n" - "attribute to compensate or by scaling all objects in the drawing."); - - Gtk::Dialog scaleDialog( _("Old Inkscape file detected (90 DPI)")); - - Gtk::Label info; - info.set_markup(msg.c_str()); - info.show(); - -#if WITH_GTKMM_3_0 - scaleDialog.get_content_area()->pack_start(info, false, false, 20); -#else - scaleDialog.get_vbox()->pack_start(info, false, false, 20); -#endif - - Gtk::CheckButton backupButton( _("Create backup file (in same directory).") ); - bool backup = prefs->getBool("/options/dpifixbackup", true); - backupButton.set_active( backup ); - backupButton.show(); - -#if WITH_GTKMM_3_0 - scaleDialog.get_content_area()->pack_start(backupButton, false, false, 20); -#else - scaleDialog.get_vbox()->pack_start(backupButton, false, false, 20); -#endif - - scaleDialog.add_button(_("Set 'viewBox'"), 1); - scaleDialog.add_button(_("Scale elements"), 2); - scaleDialog.add_button(_("Ignore"), 3); - - gint response = scaleDialog.run(); - backup = backupButton.get_active(); - prefs->setBool("/options/dpifixbackup", backup); - - if ( backup && response != 3) { - sp_file_save_backup( uri ); - } - - if (response == 1) { - - if (!root->viewBox_set) { - doc->setViewBox(Geom::Rect::from_xywh( - 0, 0, - doc->getWidth().value("px"), - doc->getHeight().value("px"))); - } - Inkscape::Util::Quantity width = - Inkscape::Util::Quantity(doc->getWidth().value("px")/ratio, "px" ); - Inkscape::Util::Quantity height = - Inkscape::Util::Quantity(doc->getHeight().value("px")/ratio,"px" ); - doc->setWidthAndHeight( width, height, false ); - - need_fix_guides = true; // Only fix guides if drawing scaled - need_fix_box3d = true; - - } else if (response == 2) { - - // std::list effects; - // Inkscape::Extension::db.get_effect_list(effects); - // std::list::iterator it = effects.begin(); - // bool did = false; - // while (it != effects.end()){ - // if (strcmp((*it)->get_id(), "org.inkscape.dpi90to96") == 0) { - // Inkscape::UI::View::View *view = desktop; - // (*it)->effect(view); - // did = true; - // break; - // } - // ++it; - // } - // if (!did) { - // std::cerr << "sp_file_open: Failed to find dpi90to96 extension." << std::endl; - // } - // need_fix_guides = true; // Only fix guides if drawing scaled - - Inkscape::Util::Quantity width = - Inkscape::Util::Quantity(doc->getWidth().value("px")/ratio, "px" ); - Inkscape::Util::Quantity height = - Inkscape::Util::Quantity(doc->getHeight().value("px")/ratio,"px" ); - doc->setWidthAndHeight( width, height, false ); - - if (!root->viewBox_set) { - - // Save preferences - bool transform_stroke = prefs->getBool("/options/transform/stroke", true); - bool transform_rectcorners = prefs->getBool("/options/transform/rectcorners", true); - bool transform_pattern = prefs->getBool("/options/transform/pattern", true); - bool transform_gradient = prefs->getBool("/options/transform/gradient", true); - - prefs->setBool("/options/transform/stroke", true); - prefs->setBool("/options/transform/rectcorners", true); - prefs->setBool("/options/transform/pattern", true); - prefs->setBool("/options/transform/gradient", true); - - Inkscape::UI::ShapeEditor::blockSetItem(true); - doc->getRoot()->scaleChildItemsRec(Geom::Scale(1/ratio),Geom::Point(0, 0), false); - Inkscape::UI::ShapeEditor::blockSetItem(false); - - // Restore preferences - prefs->setBool("/options/transform/stroke", transform_stroke); - prefs->setBool("/options/transform/rectcorners", transform_rectcorners); - prefs->setBool("/options/transform/pattern", transform_pattern); - prefs->setBool("/options/transform/gradient", transform_gradient); - - did_scaling = true; - } - - need_fix_box3d = true; - need_fix_guides = true; // Only fix guides if drawing scaled - - } else { - // Ignore - need_fix_grid_mm = true; - } - } - - // Fix guides and grids and perspective - for (SPObject *child = root->firstChild() ; child; child = child->getNext() ) { - SPNamedView *nv = dynamic_cast(child); - if (nv) { - if (need_fix_guides) { - // std::cout << "Fixing guides" << std::endl; - for (SPObject *child2 = nv->firstChild() ; child2; child2 = child2->getNext() ) { - SPGuide *gd = dynamic_cast(child2); - if (gd) { - gd->moveto( gd->getPoint() / ratio, true ); - } - } - } - - for(std::vector::const_iterator it=nv->grids.begin();it!=nv->grids.end();++it ) { - Inkscape::CanvasXYGrid *xy = dynamic_cast(*it); - if (xy) { - // std::cout << "A grid: " << xy->getSVGName() << std::endl; - // std::cout << " Origin: " << xy->origin - // << " Spacing: " << xy->spacing << std::endl; - // std::cout << (xy->isLegacy()?" Legacy":" Not Legacy") << std::endl; - Geom::Scale scale = doc->getDocumentScale(); - if (xy->isLegacy()) { - if (xy->isPixel()) { - if (need_fix_grid_mm) { - xy->Scale( Geom::Scale(1,1) ); // See note below - } else { - scale *= Geom::Scale(ratio,ratio); - xy->Scale( scale.inverse() ); /* *** */ - } - } else { - if (need_fix_grid_mm) { - xy->Scale( Geom::Scale(ratio,ratio) ); - } else { - xy->Scale( scale.inverse() ); /* *** */ - } - } - } else { - if (need_fix_guides) { - if(did_scaling){ - xy->Scale( Geom::Scale(ratio,ratio).inverse() ); - } else { - // HACK: Scaling the document does not seem to cause - // grids defined in document units to be updated. - // This forces an update. - xy->Scale( Geom::Scale(1,1) ); - } - } - } - } - } - } // If SPNamedView - - SPDefs *defs = dynamic_cast(child); - if (defs && need_fix_box3d) { - for (SPObject *child = defs->firstChild() ; child; child = child->getNext() ) { - Persp3D* persp3d = dynamic_cast(child); - if (persp3d) { - std::vector tokens; - - const gchar* vp_x = persp3d->getAttribute("inkscape:vp_x"); - const gchar* vp_y = persp3d->getAttribute("inkscape:vp_y"); - const gchar* vp_z = persp3d->getAttribute("inkscape:vp_z"); - const gchar* vp_o = persp3d->getAttribute("inkscape:persp3d-origin"); - // std::cout << "Found Persp3d: " - // << " vp_x: " << vp_x - // << " vp_y: " << vp_y - // << " vp_z: " << vp_z << std::endl; - Proj::Pt2 pt_x (vp_x); - Proj::Pt2 pt_y (vp_y); - Proj::Pt2 pt_z (vp_z); - Proj::Pt2 pt_o (vp_o); - pt_x = pt_x * (1.0/ratio); - pt_y = pt_y * (1.0/ratio); - pt_z = pt_z * (1.0/ratio); - pt_o = pt_o * (1.0/ratio); - persp3d->setAttribute("inkscape:vp_x",pt_x.coord_string()); - persp3d->setAttribute("inkscape:vp_y",pt_y.coord_string()); - persp3d->setAttribute("inkscape:vp_z",pt_z.coord_string()); - persp3d->setAttribute("inkscape:persp3d-origin",pt_o.coord_string()); - } - } - } - } // Look for SPNamedView and SPDefs loop - - // desktop->getDocument()->ensureUpToDate(); // Does not update box3d! - DocumentUndo::done(desktop->getDocument(), SP_VERB_NONE, _("Update Document")); - - } // If old Inkscape version - } // If use_gui + // Fix dpi of old files + if (sp_version_inside_range(root->version.inkscape, 0, 1, 0, 92)) { + sp_file_convert_dpi(doc); + } + } // If use_gui // resize the window to match the document properties sp_namedview_window_from_document(desktop); === modified file 'src/file.h' --- src/file.h 2017-02-02 01:55:39 +0000 +++ src/file.h 2017-02-03 21:32:14 +0000 @@ -205,6 +205,9 @@ void sp_file_vacuum (SPDocument *doc); void sp_file_convert_text_baseline_spacing(SPDocument *doc); void sp_file_convert_font_name(SPDocument *doc); +void sp_file_convert_dpi(SPDocument *doc); +enum File_DPI_Fix { FILE_DPI_UNCHANGED = 0, FILE_DPI_VIEWBOX_SCALED, FILE_DPI_DOCUMENT_SCALED }; +extern int sp_file_convert_dpi_method_commandline; #endif // SEEN_SP_FILE_H === modified file 'src/main.cpp' --- src/main.cpp 2017-02-02 01:52:58 +0000 +++ src/main.cpp 2017-02-03 21:32:14 +0000 @@ -15,6 +15,7 @@ * ... and various people who have worked with various projects * Jon A. Cruz * Abhishek Sharma + + Marc Jeanmougin * * Copyright (C) 1999-2004 authors * Copyright (C) 2001-2002 Ximian, Inc. @@ -178,6 +179,7 @@ SP_ARG_VERSION, SP_ARG_VACUUM_DEFS, SP_ARG_NO_CONVERT_TEXT_BASELINE_SPACING, + SP_ARG_CONVERT_DPI_METHOD, #ifdef WITH_DBUS SP_ARG_DBUS_LISTEN, SP_ARG_DBUS_NAME, @@ -281,6 +283,7 @@ sp_query_id = NULL; sp_vacuum_defs = FALSE; sp_no_convert_text_baseline_spacing = FALSE; + sp_file_convert_dpi_method_commandline = -1; #ifdef WITH_DBUS sp_dbus_listen = FALSE; sp_dbus_name = NULL; @@ -532,6 +535,11 @@ N_("Do not fix legacy (pre-0.92) files' text baseline spacing on opening."), NULL}, + {"convert-dpi-method", 0, + POPT_ARG_STRING, NULL, SP_ARG_CONVERT_DPI_METHOD, + N_("Method used to convert pre-.92 document dpi, if needed."), + "[none|scale-viewbox|scale-document]"}, + POPT_AUTOHELP POPT_TABLEEND }; @@ -2275,6 +2283,21 @@ } break; } + case SP_ARG_CONVERT_DPI_METHOD: { + gchar const *arg = poptGetOptArg(ctx); + if (arg != NULL) { + if (!strcmp(arg,"none")) { + sp_file_convert_dpi_method_commandline = FILE_DPI_UNCHANGED; + } else if (!strcmp(arg,"scale-viewbox")) { + sp_file_convert_dpi_method_commandline = FILE_DPI_VIEWBOX_SCALED; + } else if (!strcmp(arg,"scale-document")) { + sp_file_convert_dpi_method_commandline = FILE_DPI_DOCUMENT_SCALED; + } else { + g_warning("Invalid update option"); + } + } + break; + } case POPT_ERROR_BADOPT: { g_warning ("Invalid option %s", poptBadOption(ctx, 0)); exit(1);