summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Smith <john.smith7545@yahoo.com>2012-07-04 00:48:30 +0000
committerJohn Smith <removethis.john.q.public@bigmail.com>2012-07-04 00:48:30 +0000
commit53fe022959ca3f120d07401366bb2a9e5618f262 (patch)
tree5aca33684699923382cf3ccd6a5c445f85f103fd /src
parentemf import. missing tick marks (Bug 715692) (diff)
downloadinkscape-53fe022959ca3f120d07401366bb2a9e5618f262.tar.gz
inkscape-53fe022959ca3f120d07401366bb2a9e5618f262.zip
Fix for 168658 : Font substitution warning dialog
(bzr r11522)
Diffstat (limited to 'src')
-rw-r--r--src/file.cpp4
-rw-r--r--src/libnrtype/Layout-TNG-Output.cpp12
-rw-r--r--src/libnrtype/Layout-TNG.h3
-rw-r--r--src/selection-chemistry.h2
-rw-r--r--src/ui/dialog/Makefile_insert2
-rw-r--r--src/ui/dialog/font-substitution.cpp267
-rw-r--r--src/ui/dialog/font-substitution.h64
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp13
-rw-r--r--src/ui/dialog/inkscape-preferences.h1
9 files changed, 364 insertions, 4 deletions
diff --git a/src/file.cpp b/src/file.cpp
index 5dab48d75..b895c6591 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -64,6 +64,7 @@
#include "xml/rebase-hrefs.h"
#include "verbs.h"
#include "event-log.h"
+#include "ui/dialog/font-substitution.h"
#include <gtk/gtk.h>
#include <glib.h>
@@ -270,6 +271,9 @@ bool sp_file_open(const Glib::ustring &uri,
Glib::ustring msg = _("Broken links have been changed to point to existing files.");
desktop->showInfoDialog(msg);
}
+
+ // Check for font substitutions
+ Inkscape::UI::Dialog::FontSubstitution::getInstance().checkFontSubstitutions(doc);
}
return TRUE;
diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp
index 0ce00e43b..bf6516b42 100644
--- a/src/libnrtype/Layout-TNG-Output.cpp
+++ b/src/libnrtype/Layout-TNG-Output.cpp
@@ -340,6 +340,18 @@ static char const *weight_to_text(PangoWeight w)
return "???";
}
+Glib::ustring Layout::getFontFamily(unsigned span_index) const
+{
+ if (span_index < 0 || span_index >= _spans.size())
+ return "";
+
+ if (_spans[span_index].font) {
+ return pango_font_description_get_family(_spans[span_index].font->descr);
+ }
+
+ return "";
+}
+
Glib::ustring Layout::dumpAsText() const
{
Glib::ustring result;
diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h
index 4406d9f93..f4a09f25b 100644
--- a/src/libnrtype/Layout-TNG.h
+++ b/src/libnrtype/Layout-TNG.h
@@ -353,6 +353,9 @@ public:
void showGlyphs(CairoRenderContext *ctx) const;
#endif
+ /** Returns the font family of the indexed span */
+ Glib::ustring getFontFamily(unsigned span_index) const;
+
/** debug and unit test method. Creates a textual representation of the
contents of this object. The output is designed to be both human-readable
and comprehensible when diffed with a known-good dump. */
diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h
index 0e69fdac8..e1c8501dd 100644
--- a/src/selection-chemistry.h
+++ b/src/selection-chemistry.h
@@ -161,6 +161,8 @@ void unlock_all_in_all_layers(SPDesktop *dt);
void unhide_all(SPDesktop *dt);
void unhide_all_in_all_layers(SPDesktop *dt);
+GSList *get_all_items(GSList *list, SPObject *from, SPDesktop *desktop, bool onlyvisible, bool onlysensitive, bool ingroups, GSList const *exclude);
+
GSList *sp_degroup_list (GSList *items);
/* selection cycling */
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
index f8b95247a..ba2f53a9e 100644
--- a/src/ui/dialog/Makefile_insert
+++ b/src/ui/dialog/Makefile_insert
@@ -44,6 +44,8 @@ ink_common_sources += \
ui/dialog/filter-effects-dialog.h \
ui/dialog/find.cpp \
ui/dialog/find.h \
+ ui/dialog/font-substitution.cpp \
+ ui/dialog/font-substitution.h \
ui/dialog/floating-behavior.cpp \
ui/dialog/floating-behavior.h \
ui/dialog/glyphs.cpp \
diff --git a/src/ui/dialog/font-substitution.cpp b/src/ui/dialog/font-substitution.cpp
new file mode 100644
index 000000000..b294490a3
--- /dev/null
+++ b/src/ui/dialog/font-substitution.cpp
@@ -0,0 +1,267 @@
+/*
+ * Authors:
+ *
+ * Copyright (C) 2012 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <set>
+#include "font-substitution.h"
+
+#include "inkscape.h"
+#include "desktop.h"
+#include "document.h"
+#include "selection.h"
+
+#include "dialogs/dialog-events.h"
+#include "desktop-handles.h"
+#include "selection-chemistry.h"
+#include "preferences.h"
+
+#include "xml/repr.h"
+#include "sp-defs.h"
+#include "sp-text.h"
+#include "sp-textpath.h"
+#include "sp-flowtext.h"
+#include "sp-flowdiv.h"
+#include "sp-tspan.h"
+#include "sp-tref.h"
+#include "style.h"
+#include "text-editing.h"
+
+#include "libnrtype/FontFactory.h"
+#include "libnrtype/font-instance.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+FontSubstitution::FontSubstitution()
+{
+}
+
+FontSubstitution::~FontSubstitution()
+{
+}
+
+void
+FontSubstitution::checkFontSubstitutions(SPDocument* doc)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int show_dlg = prefs->getInt("/options/font/substitutedlg", 0);
+ if (show_dlg) {
+ Glib::ustring out;
+ GSList *l = getFontReplacedItems(doc, &out);
+ if (out.length() > 0) {
+ show(out, l);
+ }
+ if (l) {
+ g_slist_free(l);
+ l = NULL;
+ }
+ }
+}
+
+void
+FontSubstitution::show(Glib::ustring out, GSList *l)
+{
+ Gtk::MessageDialog warning(_("\nSome fonts are not available and have been substituted."),
+ false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, true);
+ warning.set_resizable(true);
+ warning.set_title(_("Font substitution"));
+
+ GtkWidget *dlg = GTK_WIDGET(warning.gobj());
+ sp_transientize(dlg);
+
+ Gtk::TextView * textview = new Gtk::TextView();
+ textview->set_editable(false);
+ textview->set_wrap_mode(Gtk::WRAP_WORD);
+ textview->show();
+ textview->get_buffer()->set_text(_(out.c_str()));
+
+ Gtk::ScrolledWindow * scrollwindow = new Gtk::ScrolledWindow();
+ scrollwindow->add(*textview);
+ scrollwindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ scrollwindow->set_shadow_type(Gtk::SHADOW_IN);
+ scrollwindow->set_size_request(0, 100);
+ scrollwindow->show();
+
+ Gtk::CheckButton *cbSelect = new Gtk::CheckButton();
+ cbSelect->set_label(_("Select all the affected items"));
+ cbSelect->set_active(true);
+ cbSelect->show();
+
+ Gtk::CheckButton *cbWarning = new Gtk::CheckButton();
+ cbWarning->set_label(_("Don't show this warning again"));
+ cbWarning->show();
+
+#if GTK_CHECK_VERSION(3,0,0)
+ Gtk::VBox * box = warning.get_content_area();
+#else
+ Gtk::VBox * box = warning.get_vbox();
+#endif
+ box->set_spacing(2);
+ box->pack_start(*scrollwindow, true, true, 4);
+ box->pack_start(*cbSelect, false, false, 0);
+ box->pack_start(*cbWarning, false, false, 0);
+
+ warning.run();
+
+ if (cbWarning->get_active()) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setInt("/options/font/substitutedlg", 0);
+ }
+
+ if (cbSelect->get_active()) {
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ selection->clear();
+ selection->setList(l);
+ }
+
+}
+
+/*
+ * Find all the fonts that are in the document but not available on the users system
+ * and have been substituted for other fonts
+ *
+ * Return a list of SPItems where fonts have been substituted.
+ *
+ * Walk thru all the objects ...
+ * a. Build up a list of the objects with fonts defined in the style attribute
+ * b. Build up a list of the objects rendered fonts - taken for the objects layout/spans
+ * If there are fonts in a. that are not in b. then those fonts have been substituted.
+ */
+GSList * FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring *out)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ GSList *allList = NULL;
+ GSList *outList = NULL;
+ std::set<Glib::ustring> setErrors;
+ std::set<Glib::ustring> setFontSpans;
+ std::map<SPItem *, Glib::ustring> mapFontStyles;
+
+ allList = get_all_items(NULL, doc->getRoot(), desktop, false, false, true, NULL);
+
+ for (GSList *i = allList; i != NULL; i = i->next) {
+
+ SPItem *item = SP_ITEM(i->data);
+ SPStyle *style = item->style;
+ Glib::ustring family = "";
+
+ if (is_top_level_text_object (item)) {
+ // Should only need to check the first span, since the others should be covered by TSPAN's etc
+ family = te_get_layout(item)->getFontFamily(0);
+ setFontSpans.insert(family);
+ }
+ else if (SP_IS_TEXTPATH(item)) {
+ SPTextPath const *textpath = SP_TEXTPATH(item);
+ if (textpath->originalPath != NULL) {
+ family = SP_TEXT(item->parent)->layout.getFontFamily(0);
+ setFontSpans.insert(family);
+ }
+ }
+ else if (SP_IS_TSPAN(item) || SP_IS_FLOWTSPAN(item)) {
+ // is_part_of_text_subtree (item)
+ // TSPAN layout comes from the parent->layout->_spans
+ SPObject *parent_text = item;
+ while (parent_text && !SP_IS_TEXT(parent_text)) {
+ parent_text = parent_text->parent;
+ }
+ if (parent_text != NULL) {
+ family = SP_TEXT(parent_text)->layout.getFontFamily(0);
+ // Add all the spans fonts to the set
+ gint ii = 0;
+ for (SPObject *child = parent_text->firstChild() ; child ; child = child->getNext() ) {
+ family = SP_TEXT(parent_text)->layout.getFontFamily(ii);
+ setFontSpans.insert(family);
+ ii++;
+ }
+ }
+ }
+
+ if (style && style->text) {
+ gchar const *style_font = NULL;
+ if (style->text->font_family.set)
+ style_font = style->text->font_family.value;
+ else if (style->text->font_specification.set)
+ style_font = style->text->font_specification.value;
+ else if (style->text->font_family.value)
+ style_font = style->text->font_family.value;
+ else if (style->text->font_specification.value)
+ style_font = style->text->font_specification.value;
+
+ if (style_font) {
+ if (has_visible_text(item)) {
+ mapFontStyles.insert(std::make_pair (item, style_font));
+ }
+ }
+ }
+ }
+
+ // Check if any document styles are not in the actual layout
+ std::map<SPItem *, Glib::ustring>::const_iterator mapIter;
+ for (mapIter = mapFontStyles.begin(); mapIter != mapFontStyles.end(); mapIter++) {
+ SPItem *item = mapIter->first;
+ Glib::ustring font = mapIter->second;
+ std::set<Glib::ustring>::const_iterator found = setFontSpans.find(font);
+ if (found == setFontSpans.end()) {
+ Glib::ustring subName = getSubstituteFontName(font);
+ if (font != Glib::ustring("sans-serif") && font != Glib::ustring("Sans")) {
+ Glib::ustring err = Glib::ustring::compose(
+ "Font '%1' substituted with '%2'", font.c_str(), subName.c_str());
+ setErrors.insert(err);
+ outList = g_slist_prepend (outList, item);
+ }
+ }
+ }
+
+ std::set<Glib::ustring>::const_iterator setIter;
+ for (setIter = setErrors.begin(); setIter != setErrors.end(); setIter++) {
+ Glib::ustring err = (*setIter);
+ out->append(err + "\n");
+ g_warning("%s", err.c_str());
+ }
+
+ return outList;
+}
+
+
+Glib::ustring FontSubstitution::getSubstituteFontName (Glib::ustring font)
+{
+ Glib::ustring out = font;
+
+ PangoFontDescription *descr = pango_font_description_new();
+ pango_font_description_set_family(descr,font.c_str());
+ font_instance *res = (font_factory::Default())->Face(descr);
+ if (res->pFont) {
+ PangoFontDescription *nFaceDesc = pango_font_describe(res->pFont);
+ out = pango_font_description_get_family(nFaceDesc);
+ }
+ pango_font_description_free(descr);
+
+ return out;
+}
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/font-substitution.h b/src/ui/dialog/font-substitution.h
new file mode 100644
index 000000000..c1f6d970d
--- /dev/null
+++ b/src/ui/dialog/font-substitution.h
@@ -0,0 +1,64 @@
+/** @file
+ * @brief FontSubstitution dialog
+ */
+/* Authors:
+ *
+ *
+ * Copyright (C) 2012 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_FONT_SUBSTITUTION_H
+#define INKSCAPE_UI_FONT_SUBSTITUTION_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/widget.h>
+#include <gtkmm/messagedialog.h>
+#include <gtkmm/textview.h>
+#include <gtkmm/scrolledwindow.h>
+#include <glibmm/i18n.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include "sp-root.h"
+
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class FontSubstitution {
+public:
+ FontSubstitution();
+ virtual ~FontSubstitution();
+ void checkFontSubstitutions(SPDocument* doc);
+ void show(Glib::ustring out, GSList *l);
+
+ static FontSubstitution &getInstance() { return *new FontSubstitution(); }
+ Glib::ustring getSubstituteFontName (Glib::ustring font);
+
+protected:
+ GSList *getFontReplacedItems(SPDocument* doc, Glib::ustring *out);
+
+private:
+ FontSubstitution(FontSubstitution const &d);
+ FontSubstitution& operator=(FontSubstitution const &d);
+
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_FONT_SUBSTITUTION_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 2215119e7..cba72fca5 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -433,10 +433,15 @@ void InkscapePreferences::initPageTools()
this->AddSelcueCheckbox(_page_text, "/tools/text", true);
this->AddGradientCheckbox(_page_text, "/tools/text", true);
{
- PrefCheckButton* cb = Gtk::manage( new PrefCheckButton);
- cb->init ( _("Show font samples in the drop-down list"), "/tools/text/show_sample_in_list", 1);
- _page_text.add_line( false, "", *cb, "", _("Show font samples alongside font names in the drop-down list in Text bar"));
+ PrefCheckButton* cb = Gtk::manage( new PrefCheckButton);
+ cb->init ( _("Show font samples in the drop-down list"), "/tools/text/show_sample_in_list", 1);
+ _page_text.add_line( false, "", *cb, "", _("Show font samples alongside font names in the drop-down list in Text bar"));
+
+ _font_dialog.init ( _("Show font substitution warning dialog"), "/options/font/substitutedlg", false);
+ _page_text.add_line( false, "", _font_dialog, "", _("Show font substitution warning dialog when requested fonts are not available on the system"));
}
+
+
this->AddNewObjectsStyle(_page_text, "/tools/text");
//Spray
@@ -1053,7 +1058,7 @@ void InkscapePreferences::initPageBehavior()
_misc_simpl.init("/options/simplifythreshold/value", 0.0001, 1.0, 0.0001, 0.0010, 0.0010, false, false);
_page_behavior.add_line( false, _("Simplification threshold:"), _misc_simpl, "",
_("How strong is the Node tool's Simplify command by default. If you invoke this command several times in quick succession, it will act more and more aggressively; invoking it again after a pause restores the default threshold."), false);
-
+
// Selecting options
_sel_all.init ( _("Select in all layers"), "/options/kbselection/inlayer", PREFS_SELECTION_ALL, false, 0);
_sel_current.init ( _("Select only within current layer"), "/options/kbselection/inlayer", PREFS_SELECTION_LAYER, true, &_sel_all);
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index ca35cd2db..a2d3107a2 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -283,6 +283,7 @@ protected:
UI::Widget::PrefSpinButton _importexport_export;
UI::Widget::PrefSlider _snap_delay;
UI::Widget::PrefSlider _snap_weight;
+ UI::Widget::PrefCheckButton _font_dialog;
UI::Widget::PrefCheckButton _misc_comment;
UI::Widget::PrefCheckButton _misc_forkvectors;