diff options
| author | Martin Owens <doctormo@gmail.com> | 2014-03-27 01:33:44 +0000 |
|---|---|---|
| committer | Martin Owens <doctormo@gmail.com> | 2014-03-27 01:33:44 +0000 |
| commit | 5a4fb2325f60d292b47330f540b26a3279341c90 (patch) | |
| tree | d2aa7967be25450b83e625025366c618101ae49f /src/widgets/font-selector.cpp | |
| parent | The Polar Arrange Tab of the Arrange Dialog now hides the parametric (diff) | |
| parent | Remove Snap menu item and improve grid menu item text (diff) | |
| download | inkscape-5a4fb2325f60d292b47330f540b26a3279341c90.tar.gz inkscape-5a4fb2325f60d292b47330f540b26a3279341c90.zip | |
Commit a merge to trunk, with probabal errors
(bzr r11073.1.36)
Diffstat (limited to 'src/widgets/font-selector.cpp')
| -rw-r--r-- | src/widgets/font-selector.cpp | 368 |
1 files changed, 180 insertions, 188 deletions
diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp index affc6bed9..0e862638c 100644 --- a/src/widgets/font-selector.cpp +++ b/src/widgets/font-selector.cpp @@ -8,10 +8,11 @@ * Lauris Kaplinski <lauris@kaplinski.com> * bulia byak <buliabyak@users.sf.net> * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Tavmjong Bah <tavmjong@free.fr> * * Copyright (C) 1999-2001 Ximian, Inc. * Copyright (C) 2002 Lauris Kaplinski - * Copyright (C) -2007 Authors + * Copyright (C) -2013 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -31,6 +32,7 @@ #include "desktop.h" #include "widgets/font-selector.h" +#include "preferences.h" /* SPFontSelector */ @@ -49,11 +51,9 @@ struct SPFontSelector NRNameList families; NRStyleList styles; - int familyidx; - int styleidx; gfloat fontsize; bool fontsize_dirty; - font_instance *font; + Glib::ustring *fontspec; }; @@ -61,7 +61,7 @@ struct SPFontSelectorClass { GtkHBoxClass parent_class; - void (* font_set) (SPFontSelector *fsel, font_instance *font); + void (* font_set) (SPFontSelector *fsel, gchar *fontspec); }; enum { @@ -71,7 +71,7 @@ enum { static void sp_font_selector_class_init (SPFontSelectorClass *c); static void sp_font_selector_init (SPFontSelector *fsel); -static void sp_font_selector_destroy (GtkObject *object); +static void sp_font_selector_dispose (GObject *object); static void sp_font_selector_family_select_row (GtkTreeSelection *selection, SPFontSelector *fsel); @@ -83,15 +83,7 @@ static void sp_font_selector_size_changed (GtkComboBox *combobo SPFontSelector *fsel); static void sp_font_selector_emit_set (SPFontSelector *fsel); - -namespace { - const char *sizes[] = { - "4", "6", "8", "9", "10", "11", "12", "13", "14", - "16", "18", "20", "22", "24", "28", - "32", "36", "40", "48", "56", "64", "72", "144", - NULL - }; -} +static void sp_font_selector_set_sizes( SPFontSelector *fsel ); static GtkHBoxClass *fs_parent_class = NULL; static guint fs_signals[LAST_SIGNAL] = { 0 }; @@ -119,7 +111,7 @@ GType sp_font_selector_get_type() static void sp_font_selector_class_init(SPFontSelectorClass *c) { - GtkObjectClass *object_class = (GtkObjectClass *) c; + GObjectClass *object_class = G_OBJECT_CLASS(c); fs_parent_class = (GtkHBoxClass* )g_type_class_peek_parent (c); @@ -132,9 +124,21 @@ static void sp_font_selector_class_init(SPFontSelectorClass *c) G_TYPE_NONE, 1, G_TYPE_POINTER); - object_class->destroy = sp_font_selector_destroy; + object_class->dispose = sp_font_selector_dispose; +} + +static void sp_font_selector_set_size_tooltip(SPFontSelector *fsel) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); + Glib::ustring tooltip = Glib::ustring::format(_("Font size"), " (", sp_style_get_css_unit_string(unit), ")"); + gtk_widget_set_tooltip_text (fsel->size, _(tooltip.c_str())); } + +/* + * Create a widget with children for selecting font-family, font-style, and font-size. + */ static void sp_font_selector_init(SPFontSelector *fsel) { gtk_box_set_homogeneous(GTK_BOX(fsel), TRUE); @@ -152,15 +156,27 @@ static void sp_font_selector_init(SPFontSelector *fsel) gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(f), sw); - Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); - fsel->family_treeview = gtk_tree_view_new (); GtkTreeViewColumn *column = gtk_tree_view_column_new (); GtkCellRenderer *cell = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, cell, FALSE); gtk_tree_view_column_set_attributes (column, cell, "text", 0, NULL); + gtk_tree_view_column_set_cell_data_func (column, cell, + GtkTreeCellDataFunc (font_lister_cell_data_func), + NULL, NULL ); gtk_tree_view_append_column (GTK_TREE_VIEW(fsel->family_treeview), column); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(fsel->family_treeview), FALSE); + gtk_tree_view_set_row_separator_func( GTK_TREE_VIEW(fsel->family_treeview), + GtkTreeViewRowSeparatorFunc ((gpointer)font_lister_separator_func), + NULL, NULL ); + + /* Muck with style, see text-toolbar.cpp */ + gtk_widget_set_name( GTK_WIDGET(fsel->family_treeview), "font_selector_family" ); + gtk_rc_parse_string ( + "widget \"*font_selector_family\" style \"fontfamily-separator-style\""); + + + Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); Glib::RefPtr<Gtk::ListStore> store = fontlister->get_font_list(); gtk_tree_view_set_model (GTK_TREE_VIEW(fsel->family_treeview), GTK_TREE_MODEL (Glib::unwrap (store))); gtk_container_add(GTK_CONTAINER(sw), fsel->family_treeview); @@ -215,51 +231,36 @@ static void sp_font_selector_init(SPFontSelector *fsel) gtk_widget_show(hb); gtk_box_pack_start(GTK_BOX(vb), hb, FALSE, FALSE, 0); -/* -This would introduce dependency on gtk version 2.24 which is currently not available in -Trisquel GNU/Linux 4.5.1 (released on May 25th, 2011) -This conditional and its #else block can be deleted in the future. -*/ -#if GTK_CHECK_VERSION(2, 24,0) + // Font-size fsel->size = gtk_combo_box_text_new_with_entry (); -#else - fsel->size = gtk_combo_box_entry_new_text (); -#endif - gtk_widget_set_tooltip_text (fsel->size, _("Font size (px)")); + sp_font_selector_set_size_tooltip(fsel); gtk_widget_set_size_request(fsel->size, 90, -1); g_signal_connect (G_OBJECT(fsel->size), "changed", G_CALLBACK (sp_font_selector_size_changed), fsel); gtk_box_pack_end (GTK_BOX(hb), fsel->size, FALSE, FALSE, 0); GtkWidget *l = gtk_label_new(_("Font size:")); gtk_widget_show_all (l); - gtk_box_pack_end(GTK_BOX (hb), l, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX (hb), l, TRUE, TRUE, 0); - for (unsigned int n = 0; sizes[n]; ++n) - { -#if GTK_CHECK_VERSION(2, 24,0) - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(fsel->size), sizes[n]); -#else - gtk_combo_box_append_text (GTK_COMBO_BOX(fsel->size), sizes[n]); -#endif - } + sp_font_selector_set_sizes(fsel); gtk_widget_show_all (fsel->size); - fsel->familyidx = 0; - fsel->styleidx = 0; - fsel->fontsize = 10.0; + // Set default size... next two lines must match + gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(fsel->size))), "18.0"); + fsel->fontsize = 18.0; fsel->fontsize_dirty = false; - fsel->font = NULL; + + fsel->fontspec = new Glib::ustring; } -static void sp_font_selector_destroy(GtkObject *object) +static void sp_font_selector_dispose(GObject *object) { SPFontSelector *fsel = SP_FONT_SELECTOR (object); - if (fsel->font) { - fsel->font->Unref(); - fsel->font = NULL; + if (fsel->fontspec) { + delete fsel->fontspec; } if (fsel->families.length > 0) { @@ -272,68 +273,108 @@ static void sp_font_selector_destroy(GtkObject *object) fsel->styles.length = 0; } - if (GTK_OBJECT_CLASS(fs_parent_class)->destroy) { - GTK_OBJECT_CLASS(fs_parent_class)->destroy(object); + if (G_OBJECT_CLASS(fs_parent_class)->dispose) { + G_OBJECT_CLASS(fs_parent_class)->dispose(object); } } +// Callback when family changed, updates style list for new family. static void sp_font_selector_family_select_row(GtkTreeSelection *selection, SPFontSelector *fsel) { - GtkTreeIter iter; - GtkTreeModel *model; - GtkListStore *store; - GtkTreePath *path; - GList *list=0; + // We need our own copy of the style list store since the font-family + // may not be the same in the font-selector as stored in the font-lister + // TODO: use font-lister class for this by modifying new_font_family to accept an optional style list + // TODO: add store to SPFontSelector struct and reuse. + + // Start by getting iterator to selected font + GtkTreeModel *model; + GtkTreeIter iter; if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_model_get (model, &iter, 1, &list, -1); - fsel->familyidx = gtk_tree_path_get_indices (path)[0]; - fsel->styleidx = 0; + // Next get family name with its style list + gchar *family; + GList *list=NULL; + gtk_tree_model_get (model, &iter, 0, &family, 1, &list, -1); - store = gtk_list_store_new (1, G_TYPE_STRING); + // Find best style match for selected family with current style (e.g. of selected text). + Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance(); + Glib::ustring style = fontlister->get_font_style(); + Glib::ustring best = fontlister->get_best_style_match (family, style); + // Create our own store of styles for selected font-family and find index of best style match + int path_index = 0; + int index = 0; + GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING); // Where is this deleted? for ( ; list ; list = list->next ) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, (char*)list->data, -1); + + if( best.compare( (char*)list->data ) == 0 ) { + path_index = index; + } + ++index; } + // Attach store to tree view. Can trigger style changed signal (but not FONT_SET): gtk_tree_view_set_model (GTK_TREE_VIEW (fsel->style_treeview), GTK_TREE_MODEL (store)); - path = gtk_tree_path_new (); - gtk_tree_path_append_index (path, 0); + + // Get path to best style + GtkTreePath *path = gtk_tree_path_new (); + gtk_tree_path_append_index (path, path_index); + + // Highlight best style. Triggers style changed signal: gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)), path); gtk_tree_path_free (path); } -static void sp_font_selector_style_select_row (GtkTreeSelection *selection, +// Callback when row changed +static void sp_font_selector_style_select_row (GtkTreeSelection * /*selection*/, SPFontSelector *fsel) { - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; + if (!fsel->block_emit) + { + sp_font_selector_emit_set (fsel); + } +} - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; - path = gtk_tree_model_get_path (model, &iter); - fsel->styleidx = gtk_tree_path_get_indices (path)[0]; +/* + * Set the default list of font sizes, scaled to the users preferred unit + * TODO: This routine occurs both here and in text-toolbar. Move to font-lister? + */ +static void sp_font_selector_set_sizes( SPFontSelector *fsel ) +{ + GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model (GTK_COMBO_BOX(fsel->size))); + gtk_list_store_clear(store); - if (!fsel->block_emit) + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); + + int sizes[] = { + 4, 6, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 28, + 32, 36, 40, 48, 56, 64, 72, 144 + }; + + // Array must be same length as SPCSSUnit in style.h + float ratios[] = {1, 1, 1, 10, 4, 40, 100, 16, 8, 0.16}; + + for (unsigned int n = 0; n < G_N_ELEMENTS(sizes); ++n) { - sp_font_selector_emit_set (fsel); + double size = sizes[n] / ratios[unit]; + + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(fsel->size), Glib::ustring::format(size).c_str()); } + } +// Callback when size changed static void sp_font_selector_size_changed( GtkComboBox */*cbox*/, SPFontSelector *fsel ) { char *text = NULL; -#if GTK_CHECK_VERSION(2, 24,0) text = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (fsel->size)); -#else - text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (fsel->size)); -#endif gfloat old_size = fsel->fontsize; gchar *endptr; @@ -344,11 +385,15 @@ static void sp_font_selector_size_changed( GtkComboBox */*cbox*/, SPFontSelector value = -1; free (text); } + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int max_size = prefs->getInt("/dialogs/textandfont/maxFontSize", 10000); // somewhat arbitrary, but text&font preview freezes with too huge fontsizes + if (value <= 0) { return; // could not parse value } - if (value > 10000) - value = 10000; // somewhat arbitrary, but text&font preview freezes with too huge fontsizes + if (value > max_size) + value = max_size; fsel->fontsize = value; if ( fabs(fsel->fontsize-old_size) > 0.001) @@ -359,9 +404,13 @@ static void sp_font_selector_size_changed( GtkComboBox */*cbox*/, SPFontSelector sp_font_selector_emit_set (fsel); } + +// Called from sp_font_selector_style_select_row +// Called from sp_font_selector_size_changed +// Called indirectly for sp_font_selector_family_select_row (since style changes). +// Emits FONT_SET signal (handled by TextEdit::onFontChange, GlyphsPanel::fontChangeCB). static void sp_font_selector_emit_set (SPFontSelector *fsel) { - font_instance *font; GtkTreeSelection *selection_family; GtkTreeSelection *selection_style; @@ -369,168 +418,111 @@ static void sp_font_selector_emit_set (SPFontSelector *fsel) GtkTreeModel *model_style; GtkTreeIter iter_family; GtkTreeIter iter_style; - char *family=0, *style=0; + char *family=NULL, *style=NULL; //We need to check this here since most GtkTreeModel operations are not atomic //See GtkListStore documenation, Chapter "Atomic Operations" --mderezynski model_family = gtk_tree_view_get_model (GTK_TREE_VIEW (fsel->family_treeview)); if (!model_family) return; - model_style = gtk_tree_view_get_model (GTK_TREE_VIEW (fsel->style_treeview)); - if (!model_style) return; + model_style = gtk_tree_view_get_model (GTK_TREE_VIEW (fsel->style_treeview)); + if (!model_style ) return; selection_family = gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->family_treeview)); - selection_style = gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)); + selection_style = gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview )); if (!gtk_tree_selection_get_selected (selection_family, NULL, &iter_family)) return; - if (!gtk_tree_selection_get_selected (selection_style, NULL, &iter_style)) return; + if (!gtk_tree_selection_get_selected (selection_style, NULL, &iter_style )) return; gtk_tree_model_get (model_family, &iter_family, 0, &family, -1); - gtk_tree_model_get (model_style, &iter_style, 0, &style, -1); + gtk_tree_model_get (model_style, &iter_style, 0, &style, -1); if ((!family) || (!style)) return; - font = (font_factory::Default())->FaceFromUIStrings (family, style); + Glib::ustring fontspec = family; + fontspec += ", "; + fontspec += style; - // FIXME: when a text object uses non-available font, font==NULL and we can't set size - // (and the size shown in the widget is invalid). To fix, here we must always get some - // default font, exactly the same as sptext uses for on-canvas display, so that - // font!=NULL ever. - if (font != fsel->font || ( font && fsel->fontsize_dirty ) ) { - if ( font ) { - font->Ref(); - } - if ( fsel->font ) { - fsel->font->Unref(); - } - fsel->font = font; - g_signal_emit(GTK_OBJECT(fsel), fs_signals[FONT_SET], 0, fsel->font); - } - fsel->fontsize_dirty = false; - if (font) { - font->Unref(); - } - font = NULL; + *(fsel->fontspec) = fontspec; + + g_signal_emit(fsel, fs_signals[FONT_SET], 0, fontspec.c_str()); } GtkWidget *sp_font_selector_new() { - SPFontSelector *fsel = (SPFontSelector*) g_object_new(SP_TYPE_FONT_SELECTOR, NULL); + SPFontSelector *fsel = SP_FONT_SELECTOR(g_object_new(SP_TYPE_FONT_SELECTOR, NULL)); - return (GtkWidget *) fsel; + return GTK_WIDGET(fsel); } -void sp_font_selector_set_font (SPFontSelector *fsel, font_instance *font, double size) + +/* + * Sets the values displayed in the font-selector from a fontspec. + * It is only called from TextEdit with a new selection and from GlyphsPanel + */ +void sp_font_selector_set_fontspec (SPFontSelector *fsel, Glib::ustring fontspec, double size) { - if (font) - { - Gtk::TreePath path; - font_instance *tempFont = NULL; - - Glib::ustring family = font_factory::Default()->GetUIFamilyString(font->descr); + if (!fontspec.empty()) + { + Inkscape::FontLister *font_lister = Inkscape::FontLister::get_instance(); + std::pair<Glib::ustring, Glib::ustring> ui = font_lister->ui_from_fontspec( fontspec ); + Glib::ustring family = ui.first; + Glib::ustring style = ui.second; + + Gtk::TreePath path; try { - path = Inkscape::FontLister::get_instance()->get_row_for_font (family); + path = font_lister->get_row_for_font (family); } catch (...) { + g_warning( "Couldn't find row for font-family: %s", family.c_str() ); return; } + // High light selected family and scroll so it is in view. fsel->block_emit = TRUE; gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->family_treeview)), path.gobj()); gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->family_treeview), path.gobj(), NULL, TRUE, 0.5, 0.5); - fsel->block_emit = FALSE; + fsel->block_emit = FALSE; // TODO: Should this be moved to the end? - GList *list = 0; - GtkTreeIter iter; - GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(fsel->family_treeview)); - gtk_tree_model_get_iter (model, &iter, path.gobj()); - gtk_tree_model_get (model, &iter, 1, &list, -1); - unsigned int currentStyleNumber = 0; - unsigned int bestStyleNumber = 0; - - PangoFontDescription *incomingFont = pango_font_description_copy(font->descr); - pango_font_description_unset_fields(incomingFont, PANGO_FONT_MASK_SIZE); - - char *incomingFontString = pango_font_description_to_string(incomingFont); - - tempFont = (font_factory::Default())->FaceFromUIStrings(family.c_str(), (char*)list->data); - - PangoFontDescription *bestMatchForFont = NULL; - if (tempFont) { - bestMatchForFont = pango_font_description_copy(tempFont->descr); - tempFont->Unref(); - tempFont = NULL; - } - - pango_font_description_unset_fields(bestMatchForFont, PANGO_FONT_MASK_SIZE); - - list = list->next; - - while (list) { - currentStyleNumber++; - - tempFont = font_factory::Default()->FaceFromUIStrings(family.c_str(), (char*)list->data); - - PangoFontDescription *currentMatchForFont = NULL; - if (tempFont) { - currentMatchForFont = pango_font_description_copy(tempFont->descr); - tempFont->Unref(); - tempFont = NULL; - } - - if (currentMatchForFont) { - pango_font_description_unset_fields(currentMatchForFont, PANGO_FONT_MASK_SIZE); - - char *currentMatchString = pango_font_description_to_string(currentMatchForFont); - - if (!strcmp(incomingFontString, currentMatchString) - || pango_font_description_better_match(incomingFont, bestMatchForFont, currentMatchForFont)) { - // Found a better match for the font we are looking for - pango_font_description_free(bestMatchForFont); - bestMatchForFont = pango_font_description_copy(currentMatchForFont); - bestStyleNumber = currentStyleNumber; - } - - g_free(currentMatchString); - - pango_font_description_free(currentMatchForFont); - } - - list = list->next; + // We don't need to get best style since this is only called on a new + // selection where we already know the "best" style. + // Glib::ustring bestStyle = font_lister->get_best_style_match (family, style); + // std::cout << "Best: " << bestStyle << std::endl; + + // The "trial" style list and the regular list are the same in this case. + Gtk::TreePath path_c; + try { + path_c = font_lister->get_row_for_style( style ); + } catch (...) { + g_warning( "Couldn't find row for style: %s (%s)", style.c_str(), family.c_str() ); + return; } - - if (bestMatchForFont) - pango_font_description_free(bestMatchForFont); - if (incomingFont) - pango_font_description_free(incomingFont); - g_free(incomingFontString); - - GtkTreePath *path_c = gtk_tree_path_new (); - gtk_tree_path_append_index (path_c, bestStyleNumber); - gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)), path_c); - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->style_treeview), path_c, NULL, TRUE, 0.5, 0.5); - + + gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)), path_c.gobj()); + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->style_treeview), path_c.gobj(), NULL, TRUE, 0.5, 0.5); + if (size != fsel->fontsize) { gchar s[8]; g_snprintf (s, 8, "%.5g", size); // UI, so printf is ok gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(fsel->size))), s); fsel->fontsize = size; + sp_font_selector_set_size_tooltip(fsel); + sp_font_selector_set_sizes(fsel); } } } -font_instance* sp_font_selector_get_font(SPFontSelector *fsel) +Glib::ustring sp_font_selector_get_fontspec(SPFontSelector *fsel) { - if (fsel->font) { - fsel->font->Ref(); - } - - return fsel->font; + return *(fsel->fontspec); } +/* + * Return the font size in pixels + */ double sp_font_selector_get_size(SPFontSelector *fsel) { return fsel->fontsize; |
