From aeabdef63219b5369907c767f692e929013c3507 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 6 Feb 2013 10:07:00 +0100 Subject: Add fonts (and font-lists) used in document to top of Text tool-bar font-family drop-down menu. If font is not on system, draws strikethrough on top of font name. (bzr r12104) --- src/widgets/text-toolbar.cpp | 213 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 195 insertions(+), 18 deletions(-) (limited to 'src/widgets/text-toolbar.cpp') diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index 3eccf1d2f..8b3612db4 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -18,7 +18,7 @@ * * Copyright (C) 2004 David Turner * Copyright (C) 2003 MenTaLguY - * Copyright (C) 1999-2011 authors + * Copyright (C) 1999-2013 authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL, read the file 'COPYING' for more information @@ -39,6 +39,7 @@ #include "../desktop-handles.h" #include "../desktop-style.h" #include "document-undo.h" +#include "../sp-root.h" #include "../verbs.h" #include "../inkscape.h" #include "../connection-pool.h" @@ -105,6 +106,10 @@ static void sp_print_font( SPStyle *query ) { << " FontSpec: " << (query->text->font_specification.value ? query->text->font_specification.value : "No value") << std::endl; + std::cout << " LineHeight: " << query->line_height.computed + << " WordSpacing: " << query->word_spacing.computed + << " LetterSpacing: " << query->letter_spacing.computed + << std::endl; } static void sp_print_fontweight( SPStyle *query ) { @@ -128,40 +133,88 @@ static void sp_print_fontstyle( SPStyle *query ) { } #endif +void sp_text_toolbox_get_font_list_in_doc (SPObject *r, std::list *l); +void sp_text_toolbox_update_font_list( GtkListStore* model ); + // Format family drop-down menu. static void cell_data_func(GtkCellLayout * /*cell_layout*/, GtkCellRenderer *cell, - GtkTreeModel *tree_model, + GtkTreeModel *model, GtkTreeIter *iter, gpointer /*data*/) { gchar *family; - gtk_tree_model_get(tree_model, iter, 0, &family, -1); - gchar *const family_escaped = g_markup_escape_text(family, -1); + gboolean onSystem = false; + gtk_tree_model_get(model, iter, 0, &family, 2, &onSystem, -1); + Glib::ustring family_escaped = g_markup_escape_text(family, -1); + g_free(family); + Glib::ustring markup; + + if( !onSystem ) { + markup = ""; + + /* See if font-family on system */ + std::vector tokens = Glib::Regex::split_simple("\\s*,\\s*", family_escaped ); + for( size_t i=0; i < tokens.size(); ++i ) { + + Glib::ustring token = tokens[i]; + + GtkTreeIter iter; + gboolean valid; + gchar *family = 0; + gboolean onSystem = true; + gboolean found = false; + for( valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(model), &iter ); + valid; + valid = gtk_tree_model_iter_next( GTK_TREE_MODEL(model), &iter ) ) { + + gtk_tree_model_get(model, &iter, 0, &family, 2, &onSystem, -1); + if( onSystem && token.compare( family ) == 0 ) { + found = true; + break; + } + } + if( found ) { + markup += g_markup_escape_text(token.c_str(), -1); + markup += ", "; + } else { + markup += ""; + markup += g_markup_escape_text(token.c_str(), -1); + markup += ""; + markup += ", "; + } + } + // Remove extra comma and space from end. + if( markup.size() >= 2 ) { + markup.resize( markup.size()-2 ); + } + markup += ""; + // std::cout << markup << std::endl; + } else { + markup = family_escaped; + } Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int show_sample = prefs->getInt("/tools/text/show_sample_in_list", 1); if (show_sample) { Glib::ustring sample = prefs->getString("/tools/text/font_sample"); - gchar *const sample_escaped = g_markup_escape_text(sample.data(), -1); - - std::stringstream markup; - markup << family_escaped << " " << sample_escaped << ""; - g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL); + Glib::ustring sample_escaped = g_markup_escape_text(sample.data(), -1); - g_free(sample_escaped); - } else { - g_object_set (G_OBJECT (cell), "markup", family_escaped, NULL); + markup += " "; + markup += sample_escaped; + markup += ""; } + + g_object_set (G_OBJECT (cell), "markup", markup.c_str(), NULL); + // This doesn't work for two reasons... it set both selected and not selected backgrounds // to white.. which means that white foreground text is invisible. It also only effects // the text region, leaving the padding untouched. // g_object_set (G_OBJECT (cell), "cell-background", "white", "cell-background-set", true, NULL); - g_free(family); - g_free(family_escaped); } /* @@ -256,7 +309,6 @@ static void sp_text_fontstyle_populate(GObject *tbl, font_instance *font=NULL) } else if (current_style) { ink_comboboxentry_action_set_active_text( fontStyleAction, current_style ); } - } // Font family @@ -1184,6 +1236,14 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + // Update font list, but only if widget already created. + Ink_ComboBoxEntry_Action* fontFamilyAction = + INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) ); + if( fontFamilyAction->combobox != NULL ) { + sp_text_toolbox_update_font_list( GTK_LIST_STORE(ink_comboboxentry_action_get_model(fontFamilyAction)) ); + } + + // Only flowed text can be justified, only normal text can be kerned... // Find out if we have flowed text now so we can use it several places gboolean isFlow = false; @@ -1238,8 +1298,6 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ // To ensure the value of the combobox is properly set on start-up, only mark // the prefs set if the combobox has already been constructed. - Ink_ComboBoxEntry_Action* fontFamilyAction = - INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) ); if( fontFamilyAction->combobox != NULL ) { g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(TRUE)); } @@ -1482,6 +1540,124 @@ sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl) sp_text_toolbox_selection_changed (NULL, tbl); } + +/* Recursively extract all "font-family" attributes from a document. */ +void +sp_text_toolbox_get_font_list_in_doc_recursive (SPObject *r, std::list *l) +{ + if (!r) { + return; + } + + const gchar *style = r->getRepr()->attribute("style"); + if( style != NULL ) { + //std::cout << style << std::endl; + std::vector tokens = Glib::Regex::split_simple(";", style ); + for( size_t i=0; i < tokens.size(); ++i ) { + Glib::ustring token = tokens[i]; + size_t found = token.find("font-family:"); + if( found != Glib::ustring::npos ) { + // Remove "font-family:" + token.erase(found,12); + // Remove any leading single or double quote + if( token[0] == '\'' || token[0] == '"' ) { + token.erase(0,1); + } + // Remove any trailing single or double quote + if( token[token.length()-1] == '\'' || token[token.length()-1] == '"' ) { + token.erase(token.length()-1); + } + l->push_back( token ); + } + } + } + + for (SPObject *child = r->firstChild(); child; child = child->getNext()) { + sp_text_toolbox_get_font_list_in_doc_recursive( child, l ); + } +} + +/* Extract all unique "font-family" attributes (including font-family fallbacks) + * from a document in a reverse sorted list. + */ +void +sp_text_toolbox_get_font_list_in_doc (SPObject *r, std::list *l) { + + sp_text_toolbox_get_font_list_in_doc_recursive (r, l); + + l->sort(); + l->unique(); + l->reverse(); + + // for(std::list::iterator i = l->begin(); i != l->end(); ++i) { + // std::cout << " font_family in doc: " << *i << std::endl; + // } +} + +/* Update font-family list with "font-family" attributes used in a document. */ +void +sp_text_toolbox_update_font_list( GtkListStore* model ) { + + /* Create default styles for use when font-family is unknown on system. */ + static GList *default_styles = NULL; + if( default_styles == NULL ) { + default_styles = g_list_append( default_styles, g_strdup("Normal") ); + default_styles = g_list_append( default_styles, g_strdup("Italic") ); + default_styles = g_list_append( default_styles, g_strdup("Bold") ); + default_styles = g_list_append( default_styles, g_strdup("Bold Italic") ); + } + + /* Get "font-family" attributes used in document */ + std::list fontfamilies; + sp_text_toolbox_get_font_list_in_doc( (sp_desktop_document(SP_ACTIVE_DESKTOP))->getRoot(), &fontfamilies ); + + /* Delete all old doc font-family entries */ + GtkTreeIter iter; + gboolean valid; + for( valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(model), &iter ); valid; ) { + gchar *family = 0; + gboolean onSystem = true; + gtk_tree_model_get( GTK_TREE_MODEL(model), &iter, 0, &family, 2, &onSystem, -1 ); + //std::cout << "List: " << family << ": " << (onSystem ? "Yes" : "No") << std::endl; + if( !onSystem ) { + valid = gtk_list_store_remove( model, &iter ); + } else { + valid = gtk_tree_model_iter_next( GTK_TREE_MODEL(model), &iter ); + } + } + + /* Insert doc font-family entries, list is already reverse sorted with duplicates removed. */ + std::list::iterator i; + for(i=fontfamilies.begin(); i != fontfamilies.end(); ++i) { + + GList *styles = default_styles; + gtk_list_store_insert( model, &iter, 0 ); // iter points to new row + + /* See if font-family (or first in fallback list) is on system. If so, get styles. */ + std::vector tokens = Glib::Regex::split_simple(",", *i ); + if( !tokens[0].empty() ) { + + GtkTreeIter iter2; + gboolean valid2; + for( valid2 = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(model), &iter2 ); + valid2; + valid2 = gtk_tree_model_iter_next( GTK_TREE_MODEL(model), &iter2 ) ) { + + gchar* family = 0; + gboolean onSystem = true; + gtk_tree_model_get( GTK_TREE_MODEL(model), &iter2, 0, &family, 2, &onSystem, -1 ); + if( onSystem && tokens[0].compare( family ) == 0 ) { + gtk_tree_model_get( GTK_TREE_MODEL(model), &iter2, 1, &styles, -1 ); + break; + } + } + + } + + gtk_list_store_set( model, &iter, 0, (*i).c_str(), 1, styles, 2, false, -1 ); + } +} + // Define all the "widgets" in the toolbar. void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) { @@ -1498,6 +1674,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje // Font list Glib::RefPtr store = Inkscape::FontLister::get_instance()->get_font_list(); GtkListStore* model = store->gobj(); + sp_text_toolbox_update_font_list( model ); Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontFamilyAction", _("Font Family"), -- cgit v1.2.3 From a3d3d3df4c67f666083e7c4c2ea56bb94705bbbf Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 7 Feb 2013 12:47:37 +0100 Subject: Add separator between fonts in document and fonts on sytem in font-family drop-down menu. Separator style depends on GTK theme (may be invisible). (bzr r12105) --- src/widgets/text-toolbar.cpp | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'src/widgets/text-toolbar.cpp') diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index 8b3612db4..42d309994 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -217,6 +217,16 @@ static void cell_data_func(GtkCellLayout * /*cell_layout*/, } +// Separator function (if true, a separator will be drawn) +static gboolean separator_func(GtkTreeModel *model, + GtkTreeIter *iter, + gpointer /*data*/) +{ + gchar* text = 0; + gtk_tree_model_get(model, iter, 0, &text, -1 ); // Column 0 + return (text && strcmp(text,"separatoR") == 0); +} + /* * Fill the font style combobox with the available font styles for the selected font family * Set the selected style to that in font @@ -1626,6 +1636,13 @@ sp_text_toolbox_update_font_list( GtkListStore* model ) { } } + /* Insert separator */ + if( !fontfamilies.empty() ) { + gtk_list_store_insert( model, &iter, 0 ); // iter points to new row + gtk_list_store_set( model, &iter, 0, "separatoR", -1 ); + } + + /* Insert doc font-family entries, list is already reverse sorted with duplicates removed. */ std::list::iterator i; for(i=fontfamilies.begin(); i != fontfamilies.end(); ++i) { @@ -1676,15 +1693,17 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GtkListStore* model = store->gobj(); sp_text_toolbox_update_font_list( model ); - Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontFamilyAction", - _("Font Family"), - _("Select Font Family (Alt-X to access)"), - NULL, - GTK_TREE_MODEL(model), - -1, // Entry width - 50, // Extra list width - (gpointer)cell_data_func,// Cell layout - GTK_WIDGET(desktop->canvas)); // Focus widget + Ink_ComboBoxEntry_Action* act = + ink_comboboxentry_action_new( "TextFontFamilyAction", + _("Font Family"), + _("Select Font Family (Alt-X to access)"), + NULL, + GTK_TREE_MODEL(model), + -1, // Entry width + 50, // Extra list width + (gpointer)cell_data_func, // Cell layout + (gpointer)separator_func, + GTK_WIDGET(desktop->canvas)); // Focus widget ink_comboboxentry_action_popup_enable( act ); // Enable entry completion gchar *const warning = _("Font not found on system"); ink_comboboxentry_action_set_warning( act, warning ); // Show icon with tooltip if missing font @@ -1721,6 +1740,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje 4, // Width in characters 0, // Extra list width NULL, // Cell layout + NULL, // Separator GTK_WIDGET(desktop->canvas)); // Focus widget g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontsize_value_changed), holder ); @@ -1740,6 +1760,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje 12, // Width in characters 0, // Extra list width NULL, // Cell layout + NULL, // Separator GTK_WIDGET(desktop->canvas)); // Focus widget g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontstyle_value_changed), holder ); -- cgit v1.2.3 From 55e21b98d8eda49df5d2c2d8ea940dd2d0802bc5 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 7 Feb 2013 15:14:00 +0100 Subject: Widen the separator in font-family drop-down so it is visible in more themes. (bzr r12106) --- src/widgets/text-toolbar.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/widgets/text-toolbar.cpp') diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index 42d309994..8d37891ac 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -1718,7 +1718,13 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje "{\n" " GtkComboBox::appears-as-list = 1\n" "}\n" - "widget \"*.TextFontFamilyAction_combobox\" style \"dropdown-as-list-style\""); + "widget \"*.TextFontFamilyAction_combobox\" style \"dropdown-as-list-style\"" + "style \"fontfamily-separator-style\"\n" + "{\n" + " GtkWidget::wide-separators = 1\n" + " GtkWidget::separator-height = 6\n" + "}\n" + "class \"GtkTreeView\" style \"fontfamily-separator-style\""); } /* Font size */ -- cgit v1.2.3 From 1db4e9f22c0412532f0c3fb9798cd1983a74c9de Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 8 Feb 2013 09:08:06 +0100 Subject: Better rc matching for text-toolbar font-family drop-down separator. From John Smith. (bzr r12107) --- src/widgets/text-toolbar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets/text-toolbar.cpp') diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index 8d37891ac..f19ee7cee 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -1724,7 +1724,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje " GtkWidget::wide-separators = 1\n" " GtkWidget::separator-height = 6\n" "}\n" - "class \"GtkTreeView\" style \"fontfamily-separator-style\""); + "widget \"*gtk-combobox-popup-window.GtkScrolledWindow.GtkTreeView\" style \"fontfamily-separator-style\""); } /* Font size */ -- cgit v1.2.3 From 83ae846627474ee5aad75c1f4816a3faa7240a47 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sat, 9 Feb 2013 13:52:04 +0100 Subject: Use update_font_list() in font-lister.cpp. Remove equivalent code in text-toolbar.cpp. Change separator "tag" from "separatoR" to "#" in attempt to speed up start up. (bzr r12112) --- src/widgets/text-toolbar.cpp | 100 +++---------------------------------------- 1 file changed, 6 insertions(+), 94 deletions(-) (limited to 'src/widgets/text-toolbar.cpp') diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index f19ee7cee..5ba2065b9 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -133,9 +133,6 @@ static void sp_print_fontstyle( SPStyle *query ) { } #endif -void sp_text_toolbox_get_font_list_in_doc (SPObject *r, std::list *l); -void sp_text_toolbox_update_font_list( GtkListStore* model ); - // Format family drop-down menu. static void cell_data_func(GtkCellLayout * /*cell_layout*/, GtkCellRenderer *cell, @@ -224,7 +221,7 @@ static gboolean separator_func(GtkTreeModel *model, { gchar* text = 0; gtk_tree_model_get(model, iter, 0, &text, -1 ); // Column 0 - return (text && strcmp(text,"separatoR") == 0); + return (text && strcmp(text,"#") == 0); } /* @@ -1250,7 +1247,8 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ Ink_ComboBoxEntry_Action* fontFamilyAction = INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) ); if( fontFamilyAction->combobox != NULL ) { - sp_text_toolbox_update_font_list( GTK_LIST_STORE(ink_comboboxentry_action_get_model(fontFamilyAction)) ); + Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); + fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP )); } @@ -1587,93 +1585,6 @@ sp_text_toolbox_get_font_list_in_doc_recursive (SPObject *r, std::list *l) { - - sp_text_toolbox_get_font_list_in_doc_recursive (r, l); - - l->sort(); - l->unique(); - l->reverse(); - - // for(std::list::iterator i = l->begin(); i != l->end(); ++i) { - // std::cout << " font_family in doc: " << *i << std::endl; - // } -} - -/* Update font-family list with "font-family" attributes used in a document. */ -void -sp_text_toolbox_update_font_list( GtkListStore* model ) { - - /* Create default styles for use when font-family is unknown on system. */ - static GList *default_styles = NULL; - if( default_styles == NULL ) { - default_styles = g_list_append( default_styles, g_strdup("Normal") ); - default_styles = g_list_append( default_styles, g_strdup("Italic") ); - default_styles = g_list_append( default_styles, g_strdup("Bold") ); - default_styles = g_list_append( default_styles, g_strdup("Bold Italic") ); - } - - /* Get "font-family" attributes used in document */ - std::list fontfamilies; - sp_text_toolbox_get_font_list_in_doc( (sp_desktop_document(SP_ACTIVE_DESKTOP))->getRoot(), &fontfamilies ); - - /* Delete all old doc font-family entries */ - GtkTreeIter iter; - gboolean valid; - for( valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(model), &iter ); valid; ) { - gchar *family = 0; - gboolean onSystem = true; - gtk_tree_model_get( GTK_TREE_MODEL(model), &iter, 0, &family, 2, &onSystem, -1 ); - //std::cout << "List: " << family << ": " << (onSystem ? "Yes" : "No") << std::endl; - if( !onSystem ) { - valid = gtk_list_store_remove( model, &iter ); - } else { - valid = gtk_tree_model_iter_next( GTK_TREE_MODEL(model), &iter ); - } - } - - /* Insert separator */ - if( !fontfamilies.empty() ) { - gtk_list_store_insert( model, &iter, 0 ); // iter points to new row - gtk_list_store_set( model, &iter, 0, "separatoR", -1 ); - } - - - /* Insert doc font-family entries, list is already reverse sorted with duplicates removed. */ - std::list::iterator i; - for(i=fontfamilies.begin(); i != fontfamilies.end(); ++i) { - - GList *styles = default_styles; - gtk_list_store_insert( model, &iter, 0 ); // iter points to new row - - /* See if font-family (or first in fallback list) is on system. If so, get styles. */ - std::vector tokens = Glib::Regex::split_simple(",", *i ); - if( !tokens[0].empty() ) { - - GtkTreeIter iter2; - gboolean valid2; - for( valid2 = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(model), &iter2 ); - valid2; - valid2 = gtk_tree_model_iter_next( GTK_TREE_MODEL(model), &iter2 ) ) { - - gchar* family = 0; - gboolean onSystem = true; - gtk_tree_model_get( GTK_TREE_MODEL(model), &iter2, 0, &family, 2, &onSystem, -1 ); - if( onSystem && tokens[0].compare( family ) == 0 ) { - gtk_tree_model_get( GTK_TREE_MODEL(model), &iter2, 1, &styles, -1 ); - break; - } - } - - } - - gtk_list_store_set( model, &iter, 0, (*i).c_str(), 1, styles, 2, false, -1 ); - } -} // Define all the "widgets" in the toolbar. void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) @@ -1689,9 +1600,10 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje /* Font family */ { // Font list - Glib::RefPtr store = Inkscape::FontLister::get_instance()->get_font_list(); + Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); + fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP )); + Glib::RefPtr store = fontlister->get_font_list(); GtkListStore* model = store->gobj(); - sp_text_toolbox_update_font_list( model ); Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontFamilyAction", -- cgit v1.2.3