diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/file.cpp | 4 | ||||
| -rw-r--r-- | src/libnrtype/Layout-TNG-Output.cpp | 12 | ||||
| -rw-r--r-- | src/libnrtype/Layout-TNG.h | 3 | ||||
| -rw-r--r-- | src/selection-chemistry.h | 2 | ||||
| -rw-r--r-- | src/ui/dialog/Makefile_insert | 2 | ||||
| -rw-r--r-- | src/ui/dialog/font-substitution.cpp | 267 | ||||
| -rw-r--r-- | src/ui/dialog/font-substitution.h | 64 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.cpp | 13 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.h | 1 |
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; |
