summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2017-06-06 17:15:26 +0000
committerjabiertxof <info@marker.es>2017-06-06 17:15:26 +0000
commit0cbf1e83f2a78036ae473b0a173d416acf52efd8 (patch)
tree7353975af4ca1b881ac61bc482046549d1ffcc42 /src
parentRemove silly code ;) (diff)
parentFix build with versions of Harfbuzz prior to 1.2.3. (Visualization of alterna... (diff)
downloadinkscape-0cbf1e83f2a78036ae473b0a173d416acf52efd8.tar.gz
inkscape-0cbf1e83f2a78036ae473b0a173d416acf52efd8.zip
Update to trunk
(bzr r15715)
Diffstat (limited to 'src')
-rw-r--r--src/document.cpp25
-rw-r--r--src/document.h4
-rw-r--r--src/extension/internal/pdfinput/pdf-input.cpp4
-rw-r--r--src/extension/internal/wmf-print.cpp2
-rw-r--r--src/file-update.cpp443
-rw-r--r--src/file.cpp536
-rw-r--r--src/file.h3
-rw-r--r--src/libnrtype/FontFactory.cpp103
-rw-r--r--src/libnrtype/font-instance.h3
-rw-r--r--src/libuemf/uwmf.c3
-rw-r--r--src/libuemf/uwmf.h2
-rw-r--r--src/main-cmdlinexact.cpp69
-rw-r--r--src/main.cpp23
-rw-r--r--src/sp-anchor.cpp42
-rw-r--r--src/sp-anchor.h4
-rw-r--r--src/ui/interface.cpp85
-rw-r--r--src/ui/interface.h4
-rw-r--r--src/ui/tools/measure-tool.cpp2
-rw-r--r--src/ui/widget/font-variants.cpp91
-rw-r--r--src/ui/widget/font-variants.h4
20 files changed, 847 insertions, 605 deletions
diff --git a/src/document.cpp b/src/document.cpp
index c7115f906..3a7d4408f 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;
}
@@ -481,7 +486,7 @@ SPDocument *SPDocument::createChildDoc(std::string const &uri)
SPDocument *document = NULL;
while(parent != NULL && parent->getURI() != NULL && document == NULL) {
- // Check myself and any parents int he chain
+ // Check myself and any parents in the chain
if(uri == parent->getURI()) {
document = parent;
break;
@@ -500,8 +505,14 @@ SPDocument *SPDocument::createChildDoc(std::string const &uri)
// Load a fresh document from the svg source.
if(!document) {
- const char *path = uri.c_str();
- document = createNewDoc(path, false, false, this);
+ std::string path;
+ if(uri.find('/') == -1) {
+ path = this->getBase() + uri;
+ } else {
+ path = uri;
+ }
+ std::cout << "Added base: '" << path << "'\n";
+ document = createNewDoc(path.c_str(), false, false, this);
}
return document;
}
@@ -1542,11 +1553,11 @@ static SPItem *find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Poin
* Assumes box is normalized (and g_asserts it!)
*
*/
-std::vector<SPItem*> SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups) const
+std::vector<SPItem*> SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups) const
{
std::vector<SPItem*> x;
g_return_val_if_fail(this->priv != NULL, x);
- return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, false, into_groups);
+ return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, take_insensitive, into_groups);
}
/*
@@ -1556,11 +1567,11 @@ std::vector<SPItem*> SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect con
*
*/
-std::vector<SPItem*> SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups) const
+std::vector<SPItem*> SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups) const
{
std::vector<SPItem*> x;
g_return_val_if_fail(this->priv != NULL, x);
- return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, false, into_groups);
+ return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, take_insensitive, into_groups);
}
std::vector<SPItem*> SPDocument::getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points, bool all_layers, size_t limit) const
diff --git a/src/document.h b/src/document.h
index db50f1717..92f53559f 100644
--- a/src/document.h
+++ b/src/document.h
@@ -282,8 +282,8 @@ public:
bool addResource(char const *key, SPObject *object);
bool removeResource(char const *key, SPObject *object);
const std::vector<SPObject *> getResourceList(char const *key) const;
- std::vector<SPItem*> getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const;
- std::vector<SPItem*> getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const;
+ std::vector<SPItem*> getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false) const;
+ std::vector<SPItem*> getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false) const;
SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = NULL) const;
std::vector<SPItem*> getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points, bool all_layers = true, size_t limit = 0) const ;
SPItem *getGroupAtPoint(unsigned int key, Geom::Point const &p) const;
diff --git a/src/extension/internal/pdfinput/pdf-input.cpp b/src/extension/internal/pdfinput/pdf-input.cpp
index a57396b17..2ee713085 100644
--- a/src/extension/internal/pdfinput/pdf-input.cpp
+++ b/src/extension/internal/pdfinput/pdf-input.cpp
@@ -946,8 +946,8 @@ void PdfInput::init(void) {
"<input>\n"
"<extension>.pdf</extension>\n"
"<mimetype>application/pdf</mimetype>\n"
- "<filetypename>" N_("Adobe PDF (*.pdf)") "</filetypename>\n"
- "<filetypetooltip>" N_("Adobe Portable Document Format") "</filetypetooltip>\n"
+ "<filetypename>" N_("Portable Document Format (*.pdf)") "</filetypename>\n"
+ "<filetypetooltip>" N_("Portable Document Format") "</filetypetooltip>\n"
"</input>\n"
"</inkscape-extension>", new PdfInput());
diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp
index 6dd9d895e..29dfa2716 100644
--- a/src/extension/internal/wmf-print.cpp
+++ b/src/extension/internal/wmf-print.cpp
@@ -312,7 +312,7 @@ unsigned int PrintWmf::finish(Inkscape::Extension::Print * /*mod*/)
g_error("Fatal programming error in PrintWmf::finish");
}
(void) wmf_finish(wt); // Finalize and write out the WMF
- wmf_free(&wt); // clean up
+ uwmf_free(&wt); // clean up
wmf_htable_free(&wht); // clean up
return 0;
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 <gtkmm.h>
+
+#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 <string>
#include <clocale>
#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("<b>") + doc->getName() + "</b>\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. <b>(Choose if unsure.)</b>"));
+ 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. <b>(Choose if unsure.)</b>"));
+ 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(
+ _("<small>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"
+ "<b>Scaling the whole document:</b> 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"
+ "<b>Scaling individual elements in the artwork:</b> 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 <a "
+ "href='https://inkscape.org/en/learn/faq#todo-todo-todo'>Inkscape FAQ</a>"
+ "</small>"));
+ 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<SPNamedView *>(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<SPGuide *>(child2);
+ if (gd) {
+ gd->moveto(gd->getPoint() / ratio, true);
+ }
+ }
+ }
+
+ for (std::vector<Inkscape::CanvasGrid *>::const_iterator it = nv->grids.begin(); it != nv->grids.end();
+ ++it) {
+ Inkscape::CanvasXYGrid *xy = dynamic_cast<Inkscape::CanvasXYGrid *>(*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<SPDefs *>(child);
+ if (defs && need_fix_box3d) {
+ for (SPObject *child = defs->firstChild(); child; child = child->getNext()) {
+ Persp3D *persp3d = dynamic_cast<Persp3D *>(child);
+ if (persp3d) {
+ std::vector<Glib::ustring> 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<Inkscape::Extension::Effect *> effects;
- Inkscape::Extension::db.get_effect_list(effects);
- std::list<Inkscape::Extension::Effect *>::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<Inkscape::Extension::Effect *> effects;
- Inkscape::Extension::db.get_effect_list(effects);
- std::list<Inkscape::Extension::Effect *>::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<SPNamedView *>(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<SPGuide *>(child2);
- if (gd) {
- gd->moveto( gd->getPoint() / ratio, true );
- }
- }
- }
-
- for(std::vector<Inkscape::CanvasGrid *>::const_iterator it=nv->grids.begin();it!=nv->grids.end();++it ) {
- Inkscape::CanvasXYGrid *xy = dynamic_cast<Inkscape::CanvasXYGrid *>(*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<SPDefs *>(child);
- if (defs && need_fix_box3d) {
- for (SPObject *child = defs->firstChild() ; child; child = child->getNext() ) {
- Persp3D* persp3d = dynamic_cast<Persp3D *>(child);
- if (persp3d) {
- std::vector<Glib::ustring> 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/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp
index 770616ae7..6c0999f2d 100644
--- a/src/libnrtype/FontFactory.cpp
+++ b/src/libnrtype/FontFactory.cpp
@@ -699,26 +699,26 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail)
// Empty map... bitmap fonts seem to be loaded multiple times.
res->openTypeTables.clear();
- auto const hb_face = hb_ft_face_create(res->theFace, NULL);
+ auto const face = hb_ft_face_create(res->theFace, NULL);
// First time to get size of array
- auto script_count = hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, NULL, NULL);
+ auto script_count = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, NULL, NULL);
auto const scripts_hb = g_new(hb_tag_t, script_count + 1);
// Second time to fill array (this two step process was not necessary with Pango).
- hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, &script_count, scripts_hb);
+ hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &script_count, scripts_hb);
for(unsigned int i = 0; i < script_count; ++i) {
- auto language_count = hb_ot_layout_script_get_language_tags(hb_face, HB_OT_TAG_GSUB, i, 0, NULL, NULL);
+ auto language_count = hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, NULL, NULL);
if(language_count > 0) {
auto const languages_hb = g_new(hb_tag_t, language_count + 1);
- hb_ot_layout_script_get_language_tags(hb_face, HB_OT_TAG_GSUB, i, 0, &language_count, languages_hb);
+ hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, &language_count, languages_hb);
for(unsigned int j = 0; j < language_count; ++j) {
- auto feature_count = hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i, j, 0, NULL, NULL);
+ auto feature_count = hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, j, 0, NULL, NULL);
auto const features_hb = g_new(hb_tag_t, feature_count + 1);
- hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i, j, 0, &feature_count, features_hb);
+ hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, j, 0, &feature_count, features_hb);
for(unsigned int k = 0; k < feature_count; ++k) {
++(res->openTypeTables[ extract_tag(&features_hb[k])]);
@@ -731,11 +731,11 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail)
}
else {
// Even if no languages are present there is still the default.
- auto feature_count = hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i,
+ auto feature_count = hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i,
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
0, NULL, NULL);
auto const features_hb = g_new(hb_tag_t, feature_count + 1);
- hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i,
+ hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i,
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
0, &feature_count, features_hb);
@@ -747,6 +747,91 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail)
}
}
+#if HB_VERSION_ATLEAST(1,2,3)
+ // Find glyphs in OpenType substitution tables ('gsub').
+ // Note that pango's functions are just dummies. Must use harfbuzz.
+
+ // Loop over all tables
+ for (auto table: res->openTypeTables) {
+
+ // Only look at style substitution tables ('salt', 'ss01', etc. but not 'ssty').
+ if (table.first == "salt" ||
+ (table.first[0] == 's' && table.first[1] == 's' && !(table.first[2] == 't') ) ) {
+ // std::cout << " Table: " << table.first << std::endl;
+
+ Glib::ustring unicode_characters;
+
+ unsigned int feature_index;
+ if ( hb_ot_layout_language_find_feature (face, HB_OT_TAG_GSUB,
+ 0, // Assume one script exists with index 0
+ HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
+ HB_TAG(table.first[0],
+ table.first[1],
+ table.first[2],
+ table.first[3]),
+ &feature_index ) ) {
+
+ // std::cout << " Found feature, number: " << feature_index << std::endl;
+ unsigned int lookup_indexes[32];
+ unsigned int lookup_count = 32;
+ int count = hb_ot_layout_feature_get_lookups (face, HB_OT_TAG_GSUB,
+ feature_index,
+ 0, // Start
+ &lookup_count,
+ lookup_indexes );
+ // std::cout << " Lookup count: " << count << " total: " << lookup_count << std::endl;
+
+ if (count > 0) {
+ hb_set_t* glyphs_before = NULL; // hb_set_create();
+ hb_set_t* glyphs_input = hb_set_create();
+ hb_set_t* glyphs_after = NULL; // hb_set_create();
+ hb_set_t* glyphs_output = NULL; // hb_set_create();
+
+ // For now, just look at first index
+ hb_ot_layout_lookup_collect_glyphs (face, HB_OT_TAG_GSUB,
+ lookup_indexes[0],
+ glyphs_before,
+ glyphs_input,
+ glyphs_after,
+ glyphs_output );
+
+ hb_font_t *font = hb_font_create (face);
+
+ // Without this, all functions return 0, etc.
+ hb_ft_font_set_funcs (font);
+
+ hb_codepoint_t codepoint = -1;
+ while (hb_set_next (glyphs_input, &codepoint)) {
+
+ // There is a unicode to glyph mapping function but not the inverse!
+ for (hb_codepoint_t unicode_i = 0; unicode_i < 0xffff; ++unicode_i) {
+ hb_codepoint_t glyph = 0;
+ hb_font_get_nominal_glyph (font, unicode_i, &glyph);
+ if ( glyph == codepoint) {
+ unicode_characters += (gunichar)unicode_i;
+ continue;
+ }
+ }
+ }
+ res->openTypeSubstitutions[table.first] = unicode_characters;
+
+ hb_set_destroy (glyphs_input);
+ hb_font_destroy (font);
+ }
+ } else {
+ // std::cout << " Did not find '" << table.first << "'!" << std::endl;
+ }
+ }
+ }
+ // for (auto table: res->openTypeSubstitutions) {
+ // std::cout << table.first << ": " << table.second << std::endl;
+ // }
+#else
+ std::cerr << "Requires Harfbuzz 1.2.3 for visualizing alternative glyph OpenType tables. "
+ << "Compiled with: " << HB_VERSION_STRING << "." << std::endl;
+#endif
+
+ hb_face_destroy (face);
g_free(scripts_hb);
} else {
// already here
diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h
index 2fac7c19b..52c921403 100644
--- a/src/libnrtype/font-instance.h
+++ b/src/libnrtype/font-instance.h
@@ -39,6 +39,9 @@ public:
// Map of OpenType tables found in font (convert to std::set?)
std::map<Glib::ustring, int> openTypeTables;
+ // Map of substitutions indexed by table
+ std::map<Glib::ustring, Glib::ustring> openTypeSubstitutions;
+
font_instance(void);
virtual ~font_instance(void);
diff --git a/src/libuemf/uwmf.c b/src/libuemf/uwmf.c
index 62e3d3c06..50e4075d8 100644
--- a/src/libuemf/uwmf.c
+++ b/src/libuemf/uwmf.c
@@ -1517,8 +1517,9 @@ int wmf_start(
\brief Release memory for an wmf structure in memory. Call this after wmf_finish().
\return 0 on success, >=1 on failure
\param wt WMF in memory
+ Renamed to uwmf_free to avoid conflict with libwmf
*/
-int wmf_free(
+int uwmf_free(
WMFTRACK **wt
){
WMFTRACK *wtl;
diff --git a/src/libuemf/uwmf.h b/src/libuemf/uwmf.h
index 138ffab37..529232ca9 100644
--- a/src/libuemf/uwmf.h
+++ b/src/libuemf/uwmf.h
@@ -2078,7 +2078,7 @@ typedef struct {
// Prototypes (_set first, then _get)
char *wmr_dup(const char *wmr);
int wmf_start(const char *name, uint32_t initsize, uint32_t chunksize, WMFTRACK **wt);
-int wmf_free(WMFTRACK **wt);
+int uwmf_free(WMFTRACK **wt);
int wmf_finish(WMFTRACK *wt);
int wmf_append(U_METARECORD *rec, WMFTRACK *wt, int freerec);
int wmf_header_append(U_METARECORD *rec,WMFTRACK *et, int freerec);
diff --git a/src/main-cmdlinexact.cpp b/src/main-cmdlinexact.cpp
index fc9e84dc4..eca402ab3 100644
--- a/src/main-cmdlinexact.cpp
+++ b/src/main-cmdlinexact.cpp
@@ -29,6 +29,7 @@
#include "extension/system.h"
#include "file.h"
#include <glib.h>
+#include <glib/gstdio.h>
#include "sp-root.h"
#include "document-undo.h"
#include "util/units.h"
@@ -41,13 +42,14 @@
#include <document-undo.h>
#include <ui/view/view-widget.h>
#include <ui/interface.h>
-#include <verbs.h>
+#include <io/sys.h>
#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px")
namespace
{
bool s_verbose = false;
+Glib::ustring s_yaml_filename("");
bool createDirForFilename( const std::string &filename )
{
@@ -96,10 +98,33 @@ std::vector<std::string> vectorFromString(const std::string &csv)
return result;
}
+Glib::ustring getDocumentPathRelatedYaml( const Glib::ustring &uri )
+{
+ if (g_path_is_absolute (uri.c_str()))
+ return uri;
+
+ gchar *yaml_dirname = g_path_get_dirname(s_yaml_filename.c_str());
+ gchar *document_path = g_build_filename(yaml_dirname, uri.c_str(), NULL);
+
+ Glib::ustring result(document_path);
+
+ g_free(document_path);
+ g_free(yaml_dirname);
+
+ return result;
+}
+
void xFileOpen( const Glib::ustring &uri )
{
+ Glib::ustring document_filename = getDocumentPathRelatedYaml(uri);
+
+ if (!Inkscape::IO::file_test(document_filename.c_str(), (GFileTest)(G_FILE_TEST_EXISTS))) {
+ printf("SVG document does not exist: %s\n", document_filename.c_str());
+ exit(1);
+ }
+
if (s_verbose) {
- printf("open %s\n", uri.c_str());
+ printf("open %s\n", document_filename.c_str());
fflush(stdout);
}
@@ -114,11 +139,11 @@ void xFileOpen( const Glib::ustring &uri )
SPDocument *doc = NULL;
Inkscape::Extension::Extension *key = NULL;
try {
- doc = Inkscape::Extension::open(key, uri.c_str());
+ doc = Inkscape::Extension::open(key, document_filename.c_str());
} catch (std::exception &e) {
doc = NULL;
std::string exeption_mgs = e.what();
- printf("Error: open %s:%s\n",uri.c_str(), exeption_mgs.c_str() );
+ printf("Error: open %s:%s\n",document_filename.c_str(), exeption_mgs.c_str() );
fflush(stdout);
}
@@ -157,31 +182,33 @@ void xFileOpen( const Glib::ustring &uri )
void xFileSaveAs( Inkscape::ActionContext const & context, const Glib::ustring &uri )
{
+ Glib::ustring document_filename = getDocumentPathRelatedYaml(uri);
SPDocument *doc = context.getDocument();
if (s_verbose) {
- printf("save as %s\n", uri.c_str());
+ printf("save as %s\n", document_filename.c_str());
fflush(stdout);
}
- if( createDirForFilename( uri )) {
+ if( createDirForFilename( document_filename )) {
Inkscape::Extension::save(
Inkscape::Extension::db.get("org.inkscape.output.svg.inkscape"),
- doc, uri.c_str(), false, false, true, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS);
+ doc, document_filename.c_str(), false, false, true, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS);
if (s_verbose) {
- printf("save done: %s\n", uri.c_str() );
+ printf("save done: %s\n", document_filename.c_str() );
fflush(stdout);
}
}
else {
- printf("can't create dirs for filename %s\n", uri.c_str() );
+ printf("can't create dirs for filename %s\n", document_filename.c_str() );
fflush(stdout);
}
}
void xFileExportPNG( Inkscape::ActionContext const & context, const Glib::ustring &uri )
{
+ Glib::ustring document_filename = getDocumentPathRelatedYaml(uri);
if (s_verbose) {
- printf("export png %s\n", uri.c_str());
+ printf("export png %s\n", document_filename.c_str());
fflush(stdout);
}
@@ -204,27 +231,27 @@ void xFileExportPNG( Inkscape::ActionContext const & context, const Glib::ustrin
SPNamedView *nv = desktop->getNamedView();
- ExportResult status = sp_export_png_file(doc, uri.c_str(),
+ ExportResult status = sp_export_png_file(doc, document_filename.c_str(),
Geom::Rect(Geom::Point(0,0), Geom::Point(width, height)), png_width, png_height, dpi, dpi,
nv->pagecolor, 0, 0, TRUE);
}
-void xSelectElement( Inkscape::ActionContext const & context, const Glib::ustring &uri )
+void xSelectElement( Inkscape::ActionContext const & context, const Glib::ustring &element_name )
{
if (context.getDocument() == NULL || context.getSelection() == NULL) {
return;
}
if (s_verbose) {
- printf("select element: %s\n", uri.c_str());
+ printf("select element: %s\n", element_name.c_str());
fflush(stdout);
}
SPDocument * doc = context.getDocument();
- SPObject * obj = doc->getObjectById(uri);
+ SPObject * obj = doc->getObjectById(element_name);
if (obj == NULL) {
- printf(_("Unable to find node ID: '%s'\n"), uri.c_str());
+ printf(_("Unable to find node ID: '%s'\n"), element_name.c_str());
fflush(stdout);
return;
}
@@ -233,7 +260,7 @@ void xSelectElement( Inkscape::ActionContext const & context, const Glib::ustrin
selection->add(obj);
if (s_verbose) {
- printf("select done %s\n", uri.c_str());
+ printf("select done %s\n", element_name.c_str());
fflush(stdout);
}
}
@@ -291,11 +318,13 @@ parseVerbsYAMLFile(gchar const *yaml_filename)
{
verbs_list_t verbs_list;
- FILE *fh = fopen(yaml_filename, "r");
+ FILE *fh = g_fopen(yaml_filename, "r");
if(fh == NULL) {
- printf("Failed to open file!\n");
+ printf("Failed to read from file %s\n", yaml_filename);
fflush(stdout);
- return verbs_list;
+
+ // exit with error
+ exit(1);
}
yaml_parser_t parser;
@@ -437,6 +466,8 @@ parseVerbsYAMLFile(gchar const *yaml_filename)
void
CmdLineXAction::createActionsFromYAML( gchar const *yaml_filename )
{
+ s_yaml_filename = Glib::ustring(yaml_filename);
+
verbs_list_t verbs_list = parseVerbsYAMLFile(yaml_filename);
typedef std::map<std::string,int> undo_labels_map_t;
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 <jon@oncruz.org>
* 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);
diff --git a/src/sp-anchor.cpp b/src/sp-anchor.cpp
index 78ba10c13..b40f53ee1 100644
--- a/src/sp-anchor.cpp
+++ b/src/sp-anchor.cpp
@@ -5,6 +5,7 @@
* Lauris Kaplinski <lauris@kaplinski.com>
* Abhishek Sharma
*
+ * Copyright (C) 2017 Martin Owens
* Copyright (C) 2001-2002 Lauris Kaplinski
* Copyright (C) 2001 Ximian, Inc.
*
@@ -23,6 +24,9 @@
SPAnchor::SPAnchor() : SPGroup() {
this->href = NULL;
+ this->type = NULL;
+ this->title = NULL;
+ this->page = NULL;
}
SPAnchor::~SPAnchor() {
@@ -46,6 +50,18 @@ void SPAnchor::release() {
g_free(this->href);
this->href = NULL;
}
+ if (this->type) {
+ g_free(this->type);
+ this->type = NULL;
+ }
+ if (this->title) {
+ g_free(this->title);
+ this->title = NULL;
+ }
+ if (this->page) {
+ g_free(this->page);
+ this->page = NULL;
+ }
SPGroup::release();
}
@@ -56,12 +72,21 @@ void SPAnchor::set(unsigned int key, const gchar* value) {
g_free(this->href);
this->href = g_strdup(value);
this->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ this->updatePageAnchor();
break;
-
case SP_ATTR_XLINK_TYPE:
+ g_free(this->type);
+ this->type = g_strdup(value);
+ this->updatePageAnchor();
+ this->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
case SP_ATTR_XLINK_ROLE:
case SP_ATTR_XLINK_ARCROLE:
case SP_ATTR_XLINK_TITLE:
+ g_free(this->title);
+ this->title = g_strdup(value);
+ this->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
case SP_ATTR_XLINK_SHOW:
case SP_ATTR_XLINK_ACTUATE:
case SP_ATTR_TARGET:
@@ -74,6 +99,17 @@ void SPAnchor::set(unsigned int key, const gchar* value) {
}
}
+/*
+ * Detect if this anchor qualifies as a page link and append
+ * the new page document to this document.
+ */
+void SPAnchor::updatePageAnchor() {
+ if (this->type && !strcmp(this->type, "page")) {
+ if (this->href && !this->page) {
+ this->page = this->document->createChildDoc(this->href);
+ }
+ }
+}
#define COPY_ATTR(rd,rs,key) (rd)->setAttribute((key), rs->attribute(key));
@@ -83,14 +119,14 @@ Inkscape::XML::Node* SPAnchor::write(Inkscape::XML::Document *xml_doc, Inkscape:
}
repr->setAttribute("xlink:href", this->href);
+ if (this->type) repr->setAttribute("xlink:type", this->type);
+ if (this->title) repr->setAttribute("xlink:title", this->title);
if (repr != this->getRepr()) {
// XML Tree being directly used while it shouldn't be in the
// below COPY_ATTR lines
- COPY_ATTR(repr, this->getRepr(), "xlink:type");
COPY_ATTR(repr, this->getRepr(), "xlink:role");
COPY_ATTR(repr, this->getRepr(), "xlink:arcrole");
- COPY_ATTR(repr, this->getRepr(), "xlink:title");
COPY_ATTR(repr, this->getRepr(), "xlink:show");
COPY_ATTR(repr, this->getRepr(), "xlink:actuate");
COPY_ATTR(repr, this->getRepr(), "target");
diff --git a/src/sp-anchor.h b/src/sp-anchor.h
index d17718344..2dd81f74c 100644
--- a/src/sp-anchor.h
+++ b/src/sp-anchor.h
@@ -24,10 +24,14 @@ public:
virtual ~SPAnchor();
char *href;
+ char *type;
+ char *title;
+ SPDocument *page;
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
virtual void set(unsigned int key, char const* value);
+ virtual void updatePageAnchor();
virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char* displayName() const;
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 5e85065d1..33e98a81c 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -1438,13 +1438,58 @@ ContextMenu::ContextMenu(SPDesktop *desktop, SPItem *item) :
AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_DELETE));
positionOfLastDialog = 10; // 9 in front + 1 for the separator in the next if; used to position the dialog menu entries below each other
+ Geom::Rect b(_desktop->point(),_desktop->point() + Geom::Point(1,1));
+ std::vector< SPItem * > down_items = _desktop->getDocument()->getItemsPartiallyInBox( _desktop->dkey, b, true, true);
+ bool has_down_hidden = false;
+ bool has_down_locked = false;
+ for(std::vector< SPItem * >::iterator down = down_items.begin(); down != down_items.end(); ++down){
+ if((*down)->isHidden()) {
+ has_down_hidden = true;
+ }
+ if((*down)->isLocked()) {
+ has_down_locked = true;
+ }
+ }
+ AddSeparator();
+ Gtk::MenuItem* mi;
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Hide selected objects"),1));
+ mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::HideSelected));
+ if (_desktop->selection->isEmpty()) {
+ mi->set_sensitive(false);
+ }
+ mi->show();
+ append(*mi);//insert(*mi,positionOfLastDialog++);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Unhide objects below"),1));
+ mi->signal_activate().connect(sigc::bind<std::vector< SPItem * > >(sigc::mem_fun(*this, &ContextMenu::UnHideBelow), down_items));
+ if (!has_down_hidden) {
+ mi->set_sensitive(false);
+ }
+ mi->show();
+ append(*mi);//insert(*mi,positionOfLastDialog++);
+ mi = Gtk::manage(new Gtk::MenuItem(_("Lock selected objects"),1));
+ mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::LockSelected));
+ if (_desktop->selection->isEmpty()) {
+ mi->set_sensitive(false);
+ }
+ mi->show();
+ append(*mi);//insert(*mi,positionOfLastDialog++);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Unlock objects below"),1));
+ mi->signal_activate().connect(sigc::bind<std::vector< SPItem * > >(sigc::mem_fun(*this, &ContextMenu::UnLockBelow), down_items));
+ if (!has_down_locked) {
+ mi->set_sensitive(false);
+ }
+ mi->show();
+ append(*mi);//insert(*mi,positionOfLastDialog++);
/* Item menu */
if (item!=NULL) {
AddSeparator();
MakeObjectMenu();
}
-
+ AddSeparator();
/* layer menu */
SPGroup *group=NULL;
if (item) {
@@ -1507,6 +1552,44 @@ void ContextMenu::LeaveGroup(void)
_desktop->setCurrentLayer(_desktop->currentLayer()->parent);
}
+void ContextMenu::LockSelected(void)
+{
+ auto itemlist = _desktop->selection->items();
+ for(auto i=itemlist.begin();i!=itemlist.end(); ++i) {
+ (*i)->setLocked(true);
+ }
+}
+
+void ContextMenu::HideSelected(void)
+{
+ auto itemlist =_desktop->selection->items();
+ for(auto i=itemlist.begin();i!=itemlist.end(); ++i) {
+ (*i)->setHidden(true);
+ }
+}
+
+void ContextMenu::UnLockBelow(std::vector<SPItem *> items)
+{
+ _desktop->selection->clear();
+ for(auto i=items.begin();i!=items.end(); ++i) {
+ if ((*i)->isLocked()) {
+ (*i)->setLocked(false);
+ _desktop->selection->add(*i);
+ }
+ }
+}
+
+void ContextMenu::UnHideBelow(std::vector<SPItem *> items)
+{
+ _desktop->selection->clear();
+ for(auto i=items.begin();i!=items.end(); ++i) {
+ if ((*i)->isHidden()) {
+ (*i)->setHidden(false);
+ _desktop->selection->add(*i);
+ }
+ }
+}
+
void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb)//, SPDesktop *view)//, bool radio, GSList *group)
{
SPAction *action;
diff --git a/src/ui/interface.h b/src/ui/interface.h
index 52074f0f0..a41c36cc3 100644
--- a/src/ui/interface.h
+++ b/src/ui/interface.h
@@ -172,6 +172,10 @@ class ContextMenu : public Gtk::Menu
void EnterGroup(Gtk::MenuItem* mi);
void LeaveGroup(void);
+ void LockSelected(void);
+ void HideSelected(void);
+ void UnLockBelow(std::vector<SPItem *> items);
+ void UnHideBelow(std::vector<SPItem *> items);
//////////////////////////////////////////
//callbacks for the context menu entries of an SP_TYPE_ITEM object
void ItemProperties(void);
diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp
index f3185649b..98b2c7d03 100644
--- a/src/ui/tools/measure-tool.cpp
+++ b/src/ui/tools/measure-tool.cpp
@@ -1260,7 +1260,7 @@ void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom,
std::vector<SPItem*> items;
SPDocument *doc = desktop->getDocument();
Geom::Rect rect(start_p, end_p);
- items = doc->getItemsPartiallyInBox(desktop->dkey, rect, true);
+ items = doc->getItemsPartiallyInBox(desktop->dkey, rect, false, true);
Inkscape::LayerModel *layer_model = NULL;
SPObject *current_layer = NULL;
if(desktop){
diff --git a/src/ui/widget/font-variants.cpp b/src/ui/widget/font-variants.cpp
index b386051a6..e7645b620 100644
--- a/src/ui/widget/font-variants.cpp
+++ b/src/ui/widget/font-variants.cpp
@@ -231,9 +231,17 @@ namespace Widget {
// Add tooltips
_feature_entry.set_tooltip_text( _("Feature settings in CSS form. No sanity checking is performed."));
+ _feature_list.set_justify( Gtk::JUSTIFY_LEFT );
+ _feature_list.set_line_wrap( true );
+
+ _feature_substitutions.set_justify( Gtk::JUSTIFY_LEFT );
+ _feature_substitutions.set_line_wrap( true );
+
// Add to frame
_feature_vbox.add( _feature_entry );
_feature_vbox.add( _feature_label );
+ _feature_vbox.add( _feature_list );
+ _feature_vbox.add( _feature_substitutions );
_feature_frame.add( _feature_vbox );
add( _feature_frame );
@@ -532,30 +540,65 @@ namespace Widget {
// Make list of tables not handled above... eventually add Gtk::Label with
// this info.
- // std::map<Glib::ustring,int> table_copy = res->openTypeTables;
- // if( (it = table_copy.find("liga")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("clig")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("dlig")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("hlig")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("calt")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("subs")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("sups")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("smcp")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("c2sc")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("pcap")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("unic")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("titl")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("lnum")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("onum")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("pnum")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("tnum")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("frac")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("afrc")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("ordn")) != table_copy.end() ) table_copy.erase( it );
- // if( (it = table_copy.find("zero")) != table_copy.end() ) table_copy.erase( it );
- // for(it = table_copy.begin(); it != table_copy.end(); ++it) {
- // std::cout << "Other: " << it->first << " Occurances: " << it->second << std::endl;
- // }
+ std::map<Glib::ustring,int> table_copy = res->openTypeTables;
+ if( (it = table_copy.find("liga")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("clig")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("dlig")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("hlig")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("calt")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("subs")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("sups")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("smcp")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("c2sc")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("pcap")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("unic")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("titl")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("lnum")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("onum")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("pnum")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("tnum")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("frac")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("afrc")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("ordn")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("zero")) != table_copy.end() ) table_copy.erase( it );
+ std::string ott_list = "OpenType tables not included above: ";
+ for(it = table_copy.begin(); it != table_copy.end(); ++it) {
+ // std::cout << "Other: " << it->first << " Occurances: " << it->second << std::endl;
+ ott_list += it->first;
+ ott_list += ", ";
+ }
+
+ _feature_list.set_text( ott_list.c_str() );
+
+ // "<span foreground='darkblue'>";
+ Glib::ustring markup;
+
+ for (auto table: res->openTypeSubstitutions) {
+
+ markup += table.first;
+ markup += ": ";
+
+ markup += "<span font_family='";
+ markup += sp_font_description_get_family(res->descr);
+ markup += "'>";
+ markup += Glib::Markup::escape_text(table.second);
+ markup += "</span>";
+
+ markup += " → ";
+
+ markup += "<span font_family='";
+ markup += sp_font_description_get_family(res->descr);
+ markup += "'>";
+ markup += "<span font_features='";
+ markup += table.first;
+ markup += "'>";
+ markup += Glib::Markup::escape_text(table.second);
+ markup += "</span>";
+ markup += "</span>\n";
+
+ }
+
+ _feature_substitutions.set_markup ( markup.c_str() );
} else {
std::cerr << "FontVariants::update(): Couldn't find font_instance for: "
diff --git a/src/ui/widget/font-variants.h b/src/ui/widget/font-variants.h
index d4329feff..cf8e476a9 100644
--- a/src/ui/widget/font-variants.h
+++ b/src/ui/widget/font-variants.h
@@ -86,7 +86,9 @@ protected:
Gtk::VBox _feature_vbox;
Gtk::Entry _feature_entry;
Gtk::Label _feature_label;
-
+ Gtk::Label _feature_list;
+ Gtk::Label _feature_substitutions;
+
private:
void ligatures_init();
void ligatures_callback();