From 99cc870e2202dd3bd4c63be34bb45ba09aa0bd0e Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Mon, 5 Jun 2017 00:58:45 +0200 Subject: Porting the pre-92 file update message from 0.92.x to trunk: New dialog when opening pre-0.92 files (with 90 dpi). I implemented it mostly based on mizmo's UI proposal (thanks!), with additional inputs from su_v with a few bugfixes from jabiertxof Also adds a commandline option --convert-dpi-method=[none|scale-viewbox|scale-document] to be able to batch convert files. Fixed bugs: - https://launchpad.net/bugs/1659229 (bzr r15729) --- src/document.cpp | 5 + src/file-update.cpp | 443 ++++++++++++++++++++++++++++++++++++++++++- src/file.cpp | 536 +--------------------------------------------------- src/file.h | 3 + src/main.cpp | 23 +++ 5 files changed, 477 insertions(+), 533 deletions(-) diff --git a/src/document.cpp b/src/document.cpp index 4fcc2b098..2141f65e9 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -469,6 +469,11 @@ SPDocument *SPDocument::createDoc(Inkscape::XML::Document *rdoc, sp_file_convert_font_name(document); } + /** Fix dpi (pre-92 files) **/ + if ( !(INKSCAPE.use_gui()) && sp_version_inside_range( document->root->version.inkscape, 0, 1, 0, 92 ) ) { + sp_file_convert_dpi(document); + } + return document; } diff --git a/src/file-update.cpp b/src/file-update.cpp index 8fb3b3111..c9a1b6d62 100644 --- a/src/file-update.cpp +++ b/src/file-update.cpp @@ -8,6 +8,17 @@ * Marc Jeanmougin * su_v */ +#include + +#include "extension/effect.h" +#include "extension/db.h" +#include "extension/input.h" +#include "extension/output.h" +#include "extension/system.h" + +#include "inkscape.h" +#include "preferences.h" + #include "file.h" #include "sp-root.h" #include "sp-text.h" @@ -17,13 +28,33 @@ #include "sp-object.h" #include "sp-item.h" #include "style.h" +#include "sp-defs.h" +#include "dir-util.h" #include "document.h" #include #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" + +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"))) @@ -167,6 +198,416 @@ void sp_file_convert_font_name(SPDocument *doc) 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); + Gtk::Box b; + 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); + Gtk::Box *content = scale_dialog.get_content_area(); + 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(); + choice1.signal_clicked().connect(sigc::mem_fun(b, &Gtk::Box::hide)); + choice2.signal_clicked().connect(sigc::mem_fun(b, &Gtk::Box::show)); + + 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; +/* + +// There used to be 2 "experimental" scaling methods in trunk. Considering that the method in .92.x appear to work, so I'm commenting those. + + // Save preferences + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive",true); + bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); + + prefs->setBool("/options/kbselection/onlysensitive", false); + prefs->setBool("/options/kbselection/onlyvisible", false); + + Inkscape::Selection *selection = desktop->getSelection(); + Inkscape::SelectionHelper::selectAllInAll( desktop ); + +//method 1 ... + selection->group(); + SPItem * group = selection->singleItem(); + if (group) { + group->setAttribute("transform","scale(1.06666667,1.06666667)"); + } else { + std::cerr << "sp_file_open: Failed to get group!" << std::endl; + } + selection->clear(); + selection->add( group ); + selection->ungroup(); + +// OR method 2... + + double height = root->height.computed; + selection->setScaleRelative( Geom::Point(0,height), Geom::Scale(96.0/90.0,96.0/90.0) ); + +... end method 2 + + selection->clear(); + + prefs->setBool("/options/kbselection/onlysensitive", onlysensitive); + prefs->setBool("/options/kbselection/onlyvisible", onlyvisible ); + + 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++ diff --git a/src/file.cpp b/src/file.cpp index 795df433d..43a9c6f5b 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -65,13 +65,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" using Inkscape::DocumentUndo; @@ -240,42 +233,6 @@ sp_file_exit() } -// 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 @@ -342,497 +299,12 @@ bool sp_file_open(const Glib::ustring &uri, 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)"), false); - - Gtk::Label info; - info.set_markup(msg.c_str()); - info.show(); - scaleDialog.get_content_area()->pack_start(info, false, false, 20); - - Gtk::CheckButton backupButton( _("Create backup file (in same directory).") ); - bool backup = prefs->getBool("/options/dpifixbackup", true); - backupButton.set_active( backup ); - backupButton.show(); - scaleDialog.get_content_area()->pack_start(backupButton, false, false, 20); - - scaleDialog.add_button(_("Set 'viewBox'"), 1); - scaleDialog.add_button(_("Scale elements"), 2); - scaleDialog.add_button(_("Ignore"), 3); - scaleDialog.add_button("Scale test - group", 4); - scaleDialog.add_button("Scale test - children", 5); - scaleDialog.add_button("Scale test - all", 6); - - 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; - } - did_scaling = true; - - } else if (response == 4) { - - // Save preferences - bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive",true); - bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); - - prefs->setBool("/options/kbselection/onlysensitive", false); - prefs->setBool("/options/kbselection/onlyvisible", false); - - Inkscape::Selection *selection = desktop->getSelection(); - Inkscape::SelectionHelper::selectAllInAll( desktop ); - selection->group(); - SPItem * group = selection->singleItem(); - if (group) { - group->setAttribute("transform","scale(1.06666667,1.06666667)"); - } else { - std::cerr << "sp_file_open: Failed to get group!" << std::endl; - } - selection->clear(); - selection->add( group ); - selection->ungroup(); - selection->clear(); - - prefs->setBool("/options/kbselection/onlysensitive", onlysensitive); - prefs->setBool("/options/kbselection/onlyvisible", onlyvisible ); - - did_scaling = true; - - } else if (response == 5) { - - // 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); - - } else if (response == 6) { - - // Save preferences - bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive",true); - bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); - - prefs->setBool("/options/kbselection/onlysensitive", false); - prefs->setBool("/options/kbselection/onlyvisible", false); - - Inkscape::Selection *selection = desktop->getSelection(); - Inkscape::SelectionHelper::selectAllInAll( desktop ); - - double height = root->height.computed; - selection->setScaleRelative( Geom::Point(0,height), Geom::Scale(96.0/90.0,96.0/90.0) ); - selection->clear(); - - prefs->setBool("/options/kbselection/onlysensitive", onlysensitive); - prefs->setBool("/options/kbselection/onlyvisible", onlyvisible ); - - did_scaling = true; - - } - - need_fix_box3d = false; // setScaleRelative() handles box3d - 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)"), false); - - Gtk::Label info; - info.set_markup(msg.c_str()); - info.show(); - scaleDialog.get_content_area()->pack_start(info, false, false, 20); - - Gtk::CheckButton backupButton( _("Create backup file (in same directory).") ); - bool backup = prefs->getBool("/options/dpifixbackup", true); - backupButton.set_active( backup ); - backupButton.show(); - scaleDialog.get_content_area()->pack_start(backupButton, false, false, 20); - - scaleDialog.add_button(_("Set 'viewBox'"), 1); - scaleDialog.add_button(_("Scale elements"), 2); - scaleDialog.add_button(_("Ignore"), 3); - scaleDialog.add_button("Scale test - group", 4); - scaleDialog.add_button("Scale test - children", 5); - scaleDialog.add_button("Scale test - all", 6); - - 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 - did_scaling = true; - - } else if (response == 4) { - - 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 - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive",true); - bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); - - prefs->setBool("/options/kbselection/onlysensitive", false); - prefs->setBool("/options/kbselection/onlyvisible", false); - - Inkscape::Selection *selection = desktop->getSelection(); - Inkscape::SelectionHelper::selectAllInAll( desktop ); - selection->group(); - SPItem * group = selection->singleItem(); - if (group) { - group->setAttribute("transform","scale(1.06666667,1.06666667)"); - } else { - std::cerr << "sp_file_open: Failed to get group!" << std::endl; - } - selection->clear(); - selection->add( group ); - selection->ungroup(); - selection->clear(); - - prefs->setBool("/options/kbselection/onlysensitive", onlysensitive); - prefs->setBool("/options/kbselection/onlyvisible", onlyvisible ); - - did_scaling = true; - } - - need_fix_box3d = true; - need_fix_guides = true; // Only fix guides if drawing scaled - - } else if (response == 5) { - - 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 - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - 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 if (response == 6) { - - double old_height = root->height.computed; - 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 - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive",true); - bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); - - prefs->setBool("/options/kbselection/onlysensitive", false); - prefs->setBool("/options/kbselection/onlyvisible", false); - - Inkscape::Selection *selection = desktop->getSelection(); - Inkscape::SelectionHelper::selectAllInAll( desktop ); - double height = root->height.computed; - - // So far we have just enlarged the drawing but due to the - // inverted coordinate system we must scale around the old - // height position. - selection->setScaleRelative( Geom::Point(0,old_height), Geom::Scale(96.0/90.0,96.0/90.0) ); - selection->clear(); - - prefs->setBool("/options/kbselection/onlysensitive", onlysensitive); - prefs->setBool("/options/kbselection/onlyvisible", onlyvisible ); - - did_scaling = true; - } - - need_fix_box3d = false; // setScaleRelative() handls box3s - 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 (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); sp_namedview_update_layers_from_document(desktop); diff --git a/src/file.h b/src/file.h index 2fc4ea910..c6ff61c25 100644 --- a/src/file.h +++ b/src/file.h @@ -205,6 +205,9 @@ void sp_file_print (Gtk::Window& parentWindow); 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 diff --git a/src/main.cpp b/src/main.cpp index 4c63402fb..7a786234e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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. @@ -167,6 +168,7 @@ enum { 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, @@ -278,6 +280,7 @@ static void resetCommandlineGlobals() { 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; @@ -539,6 +542,11 @@ struct poptOption options[] = { 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 }; @@ -2180,6 +2188,21 @@ sp_process_args(poptContext ctx) } 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); -- cgit v1.2.3