From 814731e7a894b2ce17695c60a0b15b2a3202511a Mon Sep 17 00:00:00 2001 From: "dmitry.zhulanov@gmail.com" <> Date: Thu, 1 Jun 2017 09:28:12 +0700 Subject: improve open .yaml error message and exit with error Fixed bugs: - https://launchpad.net/bugs/1692707 (bzr r15700.1.1) --- src/main-cmdlinexact.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main-cmdlinexact.cpp b/src/main-cmdlinexact.cpp index fc9e84dc4..2806e5b5f 100644 --- a/src/main-cmdlinexact.cpp +++ b/src/main-cmdlinexact.cpp @@ -293,9 +293,11 @@ parseVerbsYAMLFile(gchar const *yaml_filename) FILE *fh = fopen(yaml_filename, "r"); if(fh == NULL) { - printf("Failed to open file!\n"); + printf("Failed to open file %s\n", yaml_filename); fflush(stdout); - return verbs_list; + + // exit with error + exit(1); } yaml_parser_t parser; -- cgit v1.2.3 From d6c9869928a71b96996c80c5d97143ee0d674f38 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 1 Jun 2017 10:36:34 +0200 Subject: Use uniform name for input and output (and PDF is an ISO standard and no longer tied to Adobe). (bzr r15703.1.20) --- src/extension/internal/pdfinput/pdf-input.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') 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) { "\n" ".pdf\n" "application/pdf\n" - "" N_("Adobe PDF (*.pdf)") "\n" - "" N_("Adobe Portable Document Format") "\n" + "" N_("Portable Document Format (*.pdf)") "\n" + "" N_("Portable Document Format") "\n" "\n" "", new PdfInput()); -- cgit v1.2.3 From d4b3d7584914d22d357424bb657caa1906a5da33 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 1 Jun 2017 11:46:21 +0200 Subject: Avoid name conflict with libwmf (wmf_free). (bzr r15703.1.21) --- src/extension/internal/wmf-print.cpp | 2 +- src/libuemf/uwmf.c | 3 ++- src/libuemf/uwmf.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') 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/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); -- cgit v1.2.3 From 6b20733af3ca815d12168948ff6d7f3737d17541 Mon Sep 17 00:00:00 2001 From: "dmitry.zhulanov@gmail.com" <> Date: Sat, 3 Jun 2017 13:41:49 +0700 Subject: fix crash in XFileOpen Fixed bugs: - https://launchpad.net/bugs/1692699 (bzr r15700.1.2) --- src/main-cmdlinexact.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/main-cmdlinexact.cpp b/src/main-cmdlinexact.cpp index 2806e5b5f..676bf7b44 100644 --- a/src/main-cmdlinexact.cpp +++ b/src/main-cmdlinexact.cpp @@ -120,6 +120,7 @@ void xFileOpen( const Glib::ustring &uri ) std::string exeption_mgs = e.what(); printf("Error: open %s:%s\n",uri.c_str(), exeption_mgs.c_str() ); fflush(stdout); + return; } // Set viewBox if it doesn't exist -- cgit v1.2.3 From 454c66cd88665d3e9e7374e134e2215fbc8c2d38 Mon Sep 17 00:00:00 2001 From: "dmitry.zhulanov@gmail.com" <> Date: Sat, 3 Jun 2017 14:05:27 +0700 Subject: check if file exist Fixed bugs: - https://launchpad.net/bugs/1692699 (bzr r15700.1.3) --- src/main-cmdlinexact.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main-cmdlinexact.cpp b/src/main-cmdlinexact.cpp index 676bf7b44..000ad6fec 100644 --- a/src/main-cmdlinexact.cpp +++ b/src/main-cmdlinexact.cpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include #define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") @@ -98,6 +98,11 @@ std::vector vectorFromString(const std::string &csv) void xFileOpen( const Glib::ustring &uri ) { + if (!Inkscape::IO::file_test(uri.c_str(), (GFileTest)(G_FILE_TEST_EXISTS))) { + printf("document is not exists: %s\n", uri.c_str()); + return; + } + if (s_verbose) { printf("open %s\n", uri.c_str()); fflush(stdout); @@ -120,7 +125,6 @@ void xFileOpen( const Glib::ustring &uri ) std::string exeption_mgs = e.what(); printf("Error: open %s:%s\n",uri.c_str(), exeption_mgs.c_str() ); fflush(stdout); - return; } // Set viewBox if it doesn't exist -- cgit v1.2.3 From 387d4eccb3a10dbda4a15e152fdea20525d934f7 Mon Sep 17 00:00:00 2001 From: "dmitry.zhulanov@gmail.com" <> Date: Sat, 3 Jun 2017 14:59:36 +0700 Subject: handle svg documents relative to .yaml path Fixed bugs: - https://launchpad.net/bugs/1692701 (bzr r15700.1.4) --- src/main-cmdlinexact.cpp | 57 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/main-cmdlinexact.cpp b/src/main-cmdlinexact.cpp index 000ad6fec..9e7231194 100644 --- a/src/main-cmdlinexact.cpp +++ b/src/main-cmdlinexact.cpp @@ -48,6 +48,7 @@ namespace { bool s_verbose = false; +Glib::ustring s_yaml_filename(""); bool createDirForFilename( const std::string &filename ) { @@ -96,15 +97,33 @@ std::vector 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 ) { - if (!Inkscape::IO::file_test(uri.c_str(), (GFileTest)(G_FILE_TEST_EXISTS))) { - printf("document is not exists: %s\n", uri.c_str()); + Glib::ustring document_filename = getDocumentPathRelatedYaml(uri); + + if (!Inkscape::IO::file_test(document_filename.c_str(), (GFileTest)(G_FILE_TEST_EXISTS))) { + printf("document is not exists: %s\n", document_filename.c_str()); return; } if (s_verbose) { - printf("open %s\n", uri.c_str()); + printf("open %s\n", document_filename.c_str()); fflush(stdout); } @@ -119,11 +138,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); } @@ -162,31 +181,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); } @@ -209,27 +230,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; } @@ -238,7 +259,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); } } @@ -444,6 +465,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 undo_labels_map_t; -- cgit v1.2.3 From d94079b0ea0195ed9c3fee03c4efd7d34e95d429 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sat, 3 Jun 2017 15:20:04 +0200 Subject: Add list of OpenType tables available in selected font. (bzr r15703.1.22) --- src/ui/widget/font-variants.cpp | 57 ++++++++++++++++++++++++----------------- src/ui/widget/font-variants.h | 3 ++- 2 files changed, 35 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/ui/widget/font-variants.cpp b/src/ui/widget/font-variants.cpp index b386051a6..6753bbc7a 100644 --- a/src/ui/widget/font-variants.cpp +++ b/src/ui/widget/font-variants.cpp @@ -231,9 +231,13 @@ 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 ); + // Add to frame _feature_vbox.add( _feature_entry ); _feature_vbox.add( _feature_label ); + _feature_vbox.add( _feature_list ); _feature_frame.add( _feature_vbox ); add( _feature_frame ); @@ -532,30 +536,35 @@ namespace Widget { // Make list of tables not handled above... eventually add Gtk::Label with // this info. - // std::map 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 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() ); } 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..507e5fb91 100644 --- a/src/ui/widget/font-variants.h +++ b/src/ui/widget/font-variants.h @@ -86,7 +86,8 @@ protected: Gtk::VBox _feature_vbox; Gtk::Entry _feature_entry; Gtk::Label _feature_label; - + Gtk::Label _feature_list; + private: void ligatures_init(); void ligatures_callback(); -- cgit v1.2.3 From de3945431b7222ed127ed59cdae8990640b79170 Mon Sep 17 00:00:00 2001 From: "dmitry.zhulanov@gmail.com" <> Date: Sat, 3 Jun 2017 20:40:10 +0700 Subject: abort Inkscape if XFileOpen command fails Fixed bugs: - https://launchpad.net/bugs/1695606 (bzr r15700.1.5) --- src/main-cmdlinexact.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main-cmdlinexact.cpp b/src/main-cmdlinexact.cpp index 9e7231194..9827378b2 100644 --- a/src/main-cmdlinexact.cpp +++ b/src/main-cmdlinexact.cpp @@ -119,7 +119,7 @@ void xFileOpen( const Glib::ustring &uri ) if (!Inkscape::IO::file_test(document_filename.c_str(), (GFileTest)(G_FILE_TEST_EXISTS))) { printf("document is not exists: %s\n", document_filename.c_str()); - return; + exit(1); } if (s_verbose) { -- cgit v1.2.3 From 745324f2e65dec6eeec16585f5d5ca639179ded3 Mon Sep 17 00:00:00 2001 From: "dmitry.zhulanov@gmail.com" <> Date: Sat, 3 Jun 2017 20:50:01 +0700 Subject: minor fixes Fixed bugs: - https://launchpad.net/bugs/1692699 (bzr r15700.1.6) --- src/main-cmdlinexact.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main-cmdlinexact.cpp b/src/main-cmdlinexact.cpp index 9827378b2..4da138f0c 100644 --- a/src/main-cmdlinexact.cpp +++ b/src/main-cmdlinexact.cpp @@ -118,7 +118,7 @@ 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("document is not exists: %s\n", document_filename.c_str()); + printf("SVG document does not exist: %s\n", document_filename.c_str()); exit(1); } @@ -319,7 +319,7 @@ parseVerbsYAMLFile(gchar const *yaml_filename) FILE *fh = fopen(yaml_filename, "r"); if(fh == NULL) { - printf("Failed to open file %s\n", yaml_filename); + printf("Failed to read from file %s\n", yaml_filename); fflush(stdout); // exit with error -- cgit v1.2.3 From 16e2b8d276eec85a7fc138e66f438caf6acf0929 Mon Sep 17 00:00:00 2001 From: "dmitry.zhulanov@gmail.com" <> Date: Sun, 4 Jun 2017 21:21:43 +0700 Subject: replace fopen with g_fopen Fixed bugs: - https://launchpad.net/bugs/1695629 (bzr r15700.1.7) --- src/main-cmdlinexact.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/main-cmdlinexact.cpp b/src/main-cmdlinexact.cpp index 4da138f0c..eca402ab3 100644 --- a/src/main-cmdlinexact.cpp +++ b/src/main-cmdlinexact.cpp @@ -29,6 +29,7 @@ #include "extension/system.h" #include "file.h" #include +#include #include "sp-root.h" #include "document-undo.h" #include "util/units.h" @@ -317,7 +318,7 @@ 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 read from file %s\n", yaml_filename); fflush(stdout); -- cgit v1.2.3 From 33f79b9653a737c534acd45eff6da806b68c276d Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Sun, 4 Jun 2017 18:12:50 -0400 Subject: Add very raw page loading using links (bzr r15703.1.24) --- src/document.cpp | 12 +++++++++--- src/sp-anchor.cpp | 42 +++++++++++++++++++++++++++++++++++++++--- src/sp-anchor.h | 4 ++++ 3 files changed, 52 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/document.cpp b/src/document.cpp index c7115f906..4fcc2b098 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -481,7 +481,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 +500,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; } 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 * 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; -- cgit v1.2.3 From 9a1906ee1091744357b32e0159b6019dc6476544 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 r15703.1.26) --- 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(-) (limited to 'src') 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 From 443ab0f809b848675fe5a74fe2290c7dc7ca16b0 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 5 Jun 2017 21:32:59 +0200 Subject: Show glyphs with alternative styles in "Feature Settings" section of "Variants" tab of "Text and Font" dialog. (bzr r15703.1.28) --- src/libnrtype/FontFactory.cpp | 97 +++++++++++++++++++++++++++++++++++++---- src/libnrtype/font-instance.h | 3 ++ src/ui/widget/font-variants.cpp | 34 +++++++++++++++ src/ui/widget/font-variants.h | 1 + 4 files changed, 126 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 770616ae7..8d66904e0 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,85 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) } } + // 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; + // } + 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 openTypeTables; + // Map of substitutions indexed by table + std::map openTypeSubstitutions; + font_instance(void); virtual ~font_instance(void); diff --git a/src/ui/widget/font-variants.cpp b/src/ui/widget/font-variants.cpp index 6753bbc7a..e7645b620 100644 --- a/src/ui/widget/font-variants.cpp +++ b/src/ui/widget/font-variants.cpp @@ -234,10 +234,14 @@ namespace Widget { _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 ); @@ -566,6 +570,36 @@ namespace Widget { _feature_list.set_text( ott_list.c_str() ); + // ""; + Glib::ustring markup; + + for (auto table: res->openTypeSubstitutions) { + + markup += table.first; + markup += ": "; + + markup += ""; + markup += Glib::Markup::escape_text(table.second); + markup += ""; + + markup += " → "; + + markup += ""; + markup += ""; + markup += Glib::Markup::escape_text(table.second); + markup += ""; + markup += "\n"; + + } + + _feature_substitutions.set_markup ( markup.c_str() ); + } else { std::cerr << "FontVariants::update(): Couldn't find font_instance for: " << font_spec << std::endl; diff --git a/src/ui/widget/font-variants.h b/src/ui/widget/font-variants.h index 507e5fb91..cf8e476a9 100644 --- a/src/ui/widget/font-variants.h +++ b/src/ui/widget/font-variants.h @@ -87,6 +87,7 @@ protected: Gtk::Entry _feature_entry; Gtk::Label _feature_label; Gtk::Label _feature_list; + Gtk::Label _feature_substitutions; private: void ligatures_init(); -- cgit v1.2.3 From 2be6299592701cf199d74ad88fb79291d4b1e1da Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 6 Jun 2017 02:27:41 +0200 Subject: Add contextual buttons to Hide/lock and Unhide/unlock items (bzr r15703.1.29) --- src/document.cpp | 8 ++-- src/document.h | 4 +- src/ui/interface.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++- src/ui/interface.h | 4 ++ src/ui/tools/measure-tool.cpp | 2 +- 5 files changed, 95 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/document.cpp b/src/document.cpp index 2141f65e9..3a7d4408f 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1553,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 SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups) const +std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups) const { std::vector 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); } /* @@ -1567,11 +1567,11 @@ std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect con * */ -std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups) const +std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups) const { std::vector 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 SPDocument::getItemsAtPoints(unsigned const key, std::vector 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 getResourceList(char const *key) const; - std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const; - std::vector getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const; + std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false) const; + std::vector 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 getItemsAtPoints(unsigned const key, std::vector points, bool all_layers = true, size_t limit = 0) const ; SPItem *getGroupAtPoint(unsigned int key, Geom::Point const &p) 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 >(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 >(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 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 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 items); + void UnHideBelow(std::vector 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 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){ -- cgit v1.2.3 From 281f5ae5654f8b762f566a177df6e56211f3efe5 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 6 Jun 2017 10:13:53 +0200 Subject: Fix build with versions of Harfbuzz prior to 1.2.3. (Visualization of alternative glyphs requires 1.2.3.) (bzr r15703.1.30) --- src/libnrtype/FontFactory.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 8d66904e0..6c0999f2d 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -747,6 +747,7 @@ 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. @@ -825,6 +826,11 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) // 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 { -- cgit v1.2.3