diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt index 8f15a3a0da..4cd12c18c7 100644 --- a/docs/reference/gtk/gtk3-sections.txt +++ b/docs/reference/gtk/gtk3-sections.txt @@ -1634,6 +1634,8 @@ gtk_font_chooser_get_show_preview_entry gtk_font_chooser_set_show_preview_entry GtkFontFilterFunc gtk_font_chooser_set_filter_func +gtk_font_chooser_set_font_map +gtk_font_chooser_get_font_map GtkFontChooserIface diff --git a/gtk/gtkfontbutton.c b/gtk/gtkfontbutton.c index acaaddaf44..492c4d297b 100644 --- a/gtk/gtkfontbutton.c +++ b/gtk/gtkfontbutton.c @@ -58,18 +58,18 @@ */ -struct _GtkFontButtonPrivate +struct _GtkFontButtonPrivate { gchar *title; gchar *fontname; - + guint use_font : 1; guint use_size : 1; guint show_style : 1; guint show_size : 1; guint show_preview_entry : 1; - + GtkWidget *font_dialog; GtkWidget *font_label; GtkWidget *size_label; @@ -78,6 +78,7 @@ struct _GtkFontButtonPrivate PangoFontDescription *font_desc; PangoFontFamily *font_family; PangoFontFace *font_face; + PangoFontMap *font_map; gint font_size; gchar *preview_text; GtkFontFilterFunc font_filter; @@ -87,7 +88,7 @@ struct _GtkFontButtonPrivate }; /* Signals */ -enum +enum { FONT_SET, LAST_SIGNAL @@ -361,7 +362,7 @@ gtk_font_button_take_font_desc (GtkFontButton *font_button, if (pango_font_description_get_size_is_absolute (priv->font_desc)) priv->font_size = pango_font_description_get_size (priv->font_desc); - else + else priv->font_size = pango_font_description_get_size (priv->font_desc) / PANGO_SCALE; gtk_font_button_update_font_data (font_button); @@ -384,6 +385,24 @@ gtk_font_button_get_font_desc (GtkFontButton *font_button) return font_button->priv->font_desc; } +static void +gtk_font_button_set_font_map (GtkFontButton *font_button, + PangoFontMap *font_map) +{ + if (g_set_object (&font_button->priv->font_map, font_map)) + { + PangoContext *context; + + if (!font_map) + font_map = pango_cairo_font_map_get_default (); + + context = gtk_widget_get_pango_context (font_button->priv->font_label); + pango_context_set_font_map (context, font_map); + + g_object_notify (G_OBJECT (font_button), "font-map"); + } +} + static void gtk_font_button_font_chooser_notify (GObject *object, GParamSpec *pspec, @@ -636,6 +655,9 @@ gtk_font_button_set_property (GObject *object, case PROP_SHOW_SIZE: gtk_font_button_set_show_size (font_button, g_value_get_boolean (value)); break; + case GTK_FONT_CHOOSER_PROP_FONT_MAP: + gtk_font_button_set_font_map (font_button, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -680,11 +702,14 @@ gtk_font_button_get_property (GObject *object, case PROP_SHOW_SIZE: g_value_set_boolean (value, gtk_font_button_get_show_size (font_button)); break; + case GTK_FONT_CHOOSER_PROP_FONT_MAP: + g_value_set_object (value, font_button->priv->font_map); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } -} +} /** @@ -700,7 +725,7 @@ GtkWidget * gtk_font_button_new (void) { return g_object_new (GTK_TYPE_FONT_BUTTON, NULL); -} +} /** * gtk_font_button_new_with_font: @@ -1014,6 +1039,8 @@ gtk_font_button_clicked (GtkButton *button) priv->font_dialog = gtk_font_chooser_dialog_new (priv->title, NULL); font_dialog = GTK_FONT_CHOOSER (font_button->priv->font_dialog); + if (priv->font_map) + gtk_font_chooser_set_font_map (font_dialog, priv->font_map); gtk_font_chooser_set_show_preview_entry (font_dialog, priv->show_preview_entry); if (priv->preview_text) diff --git a/gtk/gtkfontchooser.c b/gtk/gtkfontchooser.c index 35591d25dc..370b1a3109 100644 --- a/gtk/gtkfontchooser.c +++ b/gtk/gtkfontchooser.c @@ -106,6 +106,18 @@ gtk_font_chooser_default_init (GtkFontChooserInterface *iface) TRUE, GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); + /** + * GtkFontChooser:font-map: + * + * A custom font map to use for this widget, instead of the + * default one. + * + * Since: 3.18 + */ + g_object_interface_install_property (iface, + g_param_spec_object ("font-map", P_("Font map"), P_("A custom PangoFontMap"), + PANGO_TYPE_FONT_MAP, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); /** * GtkFontChooser::font-activated: * @self: the object which received the signal @@ -415,3 +427,47 @@ _gtk_font_chooser_font_activated (GtkFontChooser *chooser, g_signal_emit (chooser, chooser_signals[SIGNAL_FONT_ACTIVATED], 0, fontname); } + +/** + * gtk_font_chooser_set_font_map: + * @fontchooser: a #GtkFontChooser + * @fontmap: (allow-none): a #PangoFontMap + * + * Sets a custom font map to use for this font chooser widget. + * A custom font map can be used to present application-specific + * fonts instead of or in addition to the normal system fonts. + * + * Since: 3.18 + */ +void +gtk_font_chooser_set_font_map (GtkFontChooser *fontchooser, + PangoFontMap *fontmap) +{ + g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser)); + g_return_if_fail (fontmap == NULL || PANGO_IS_FONT_MAP (fontmap)); + + g_object_set (fontchooser, "font-map", fontmap, NULL); +} + +/** + * gtk_font_chooser_get_font_map: + * @fontchooser: a #GtkFontChooser + * + * Gets the custom font map of this font chooser widget, + * or %NULL if it does not have one. + * + * Returns: (transfer full) (allow-none): a #PangoFontMap, or %NULL + * + * Since: 3.18 + */ +PangoFontMap * +gtk_font_chooser_get_font_map (GtkFontChooser *fontchooser) +{ + PangoFontMap *fontmap; + + g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser)); + + g_object_get (fontchooser, "font-map", &fontmap, NULL); + + return fontmap; +} diff --git a/gtk/gtkfontchooser.h b/gtk/gtkfontchooser.h index 1c1bbf09b1..84693c1fe4 100644 --- a/gtk/gtkfontchooser.h +++ b/gtk/gtkfontchooser.h @@ -112,6 +112,11 @@ void gtk_font_chooser_set_filter_func (GtkFontChooser *fo GtkFontFilterFunc filter, gpointer user_data, GDestroyNotify destroy); +GDK_AVAILABLE_IN_3_18 +void gtk_font_chooser_set_font_map (GtkFontChooser *fontchooser, + PangoFontMap *fontmap); +GDK_AVAILABLE_IN_3_18 +PangoFontMap * gtk_font_chooser_get_font_map (GtkFontChooser *fontchooser); G_END_DECLS diff --git a/gtk/gtkfontchooserutils.c b/gtk/gtkfontchooserutils.c index 5014883ac1..ff8ca68110 100644 --- a/gtk/gtkfontchooserutils.c +++ b/gtk/gtkfontchooserutils.c @@ -121,6 +121,9 @@ _gtk_font_chooser_install_properties (GObjectClass *klass) g_object_class_override_property (klass, GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY, "show-preview-entry"); + g_object_class_override_property (klass, + GTK_FONT_CHOOSER_PROP_FONT_MAP, + "font-map"); } /** diff --git a/gtk/gtkfontchooserutils.h b/gtk/gtkfontchooserutils.h index 7c92a64947..0a8f9f8d8d 100644 --- a/gtk/gtkfontchooserutils.h +++ b/gtk/gtkfontchooserutils.h @@ -37,6 +37,7 @@ typedef enum { GTK_FONT_CHOOSER_PROP_FONT_DESC, GTK_FONT_CHOOSER_PROP_PREVIEW_TEXT, GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY, + GTK_FONT_CHOOSER_PROP_FONT_MAP, GTK_FONT_CHOOSER_PROP_LAST } GtkFontChooserProp; diff --git a/gtk/gtkfontchooserwidget.c b/gtk/gtkfontchooserwidget.c index a991702fc1..809e336374 100644 --- a/gtk/gtkfontchooserwidget.c +++ b/gtk/gtkfontchooserwidget.c @@ -90,6 +90,8 @@ struct _GtkFontChooserWidgetPrivate GtkWidget *size_spin; GtkWidget *size_slider; + PangoFontMap *font_map; + PangoFontDescription *font_desc; GtkTreeIter font_iter; /* invalid if font not available or pointer into model (not filter_model) to the row containing font */ @@ -160,7 +162,8 @@ static void gtk_font_chooser_widget_set_show_preview_entry (GtkFontChooserWi gboolean show_preview_entry); static void gtk_font_chooser_widget_set_cell_size (GtkFontChooserWidget *fontchooser); -static void gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser); +static void gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser, + gboolean force); static gboolean visible_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data); @@ -169,6 +172,8 @@ static void gtk_font_chooser_widget_cell_data_func (GtkTreeViewColum GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data); +static void gtk_font_chooser_widget_set_font_map (GtkFontChooserWidget *fontchooser, + PangoFontMap *fontmap); static void gtk_font_chooser_widget_iface_init (GtkFontChooserIface *iface); @@ -199,6 +204,9 @@ gtk_font_chooser_widget_set_property (GObject *object, case GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY: gtk_font_chooser_widget_set_show_preview_entry (fontchooser, g_value_get_boolean (value)); break; + case GTK_FONT_CHOOSER_PROP_FONT_MAP: + gtk_font_chooser_widget_set_font_map (fontchooser, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -227,6 +235,9 @@ gtk_font_chooser_widget_get_property (GObject *object, case GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY: g_value_set_boolean (value, gtk_font_chooser_widget_get_show_preview_entry (fontchooser)); break; + case GTK_FONT_CHOOSER_PROP_FONT_MAP: + g_value_set_object (value, fontchooser->priv->font_map); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -599,7 +610,7 @@ gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser) NULL); /* Load data and set initial style-dependent parameters */ - gtk_font_chooser_widget_load_fonts (fontchooser); + gtk_font_chooser_widget_load_fonts (fontchooser, TRUE); gtk_font_chooser_widget_set_cell_size (fontchooser); gtk_font_chooser_widget_take_font_desc (fontchooser, NULL); } @@ -630,7 +641,8 @@ cmp_families (const void *a, } static void -gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser) +gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser, + gboolean force) { GtkFontChooserWidgetPrivate *priv = fontchooser->priv; GtkListStore *list_store; @@ -638,6 +650,8 @@ gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser) PangoFontFamily **families; gchar *family_and_face; guint fontconfig_timestamp; + gboolean need_reload; + PangoFontMap *font_map; g_object_get (gtk_widget_get_settings (GTK_WIDGET (fontchooser)), "gtk-fontconfig-timestamp", &fontconfig_timestamp, @@ -647,21 +661,25 @@ gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser) * other platform will set it to 0. For those systems, we fall back to * reloading the fonts every time. */ - if (fontconfig_timestamp != 0 && - priv->last_fontconfig_timestamp == fontconfig_timestamp) - return; + need_reload = fontconfig_timestamp == 0 || + fontconfig_timestamp != priv->last_fontconfig_timestamp; priv->last_fontconfig_timestamp = fontconfig_timestamp; + if (!need_reload && !force) + return; + list_store = GTK_LIST_STORE (priv->model); - pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontchooser)), - &families, - &n_families); + if (priv->font_map) + font_map = priv->font_map; + else + font_map = pango_cairo_font_map_get_default (); + pango_font_map_list_families (font_map, &families, &n_families); qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families); - g_signal_handlers_block_by_func(priv->family_face_list, cursor_changed_cb, fontchooser); + g_signal_handlers_block_by_func (priv->family_face_list, cursor_changed_cb, fontchooser); gtk_list_store_clear (list_store); g_signal_handlers_unblock_by_func (priv->family_face_list, cursor_changed_cb, fontchooser); @@ -698,9 +716,7 @@ gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser) g_free (families); /* now make sure the font list looks right */ - if (!gtk_font_chooser_widget_find_font (fontchooser, - priv->font_desc, - &priv->font_iter)) + if (!gtk_font_chooser_widget_find_font (fontchooser, priv->font_desc, &priv->font_iter)) memset (&priv->font_iter, 0, sizeof (GtkTreeIter)); gtk_font_chooser_widget_ensure_selection (fontchooser); @@ -899,6 +915,8 @@ gtk_font_chooser_widget_finalize (GObject *object) g_free (priv->preview_text); + g_clear_object (&priv->font_map); + G_OBJECT_CLASS (gtk_font_chooser_widget_parent_class)->finalize (object); } @@ -950,6 +968,12 @@ gtk_font_chooser_widget_find_font (GtkFontChooserWidget *fontchooser, return valid; } +static void +fontconfig_changed (GtkFontChooserWidget *fontchooser) +{ + gtk_font_chooser_widget_load_fonts (fontchooser, TRUE); +} + static void gtk_font_chooser_widget_screen_changed (GtkWidget *widget, GdkScreen *previous_screen) @@ -963,11 +987,11 @@ gtk_font_chooser_widget_screen_changed (GtkWidget *widget, if (previous_screen) { settings = gtk_settings_get_for_screen (previous_screen); - g_signal_handlers_disconnect_by_func (settings, gtk_font_chooser_widget_load_fonts, widget); + g_signal_handlers_disconnect_by_func (settings, fontconfig_changed, widget); } settings = gtk_widget_get_settings (widget); g_signal_connect_object (settings, "notify::gtk-fontconfig-timestamp", - G_CALLBACK (gtk_font_chooser_widget_load_fonts), widget, G_CONNECT_SWAPPED); + G_CALLBACK (fontconfig_changed), widget, G_CONNECT_SWAPPED); if (previous_screen == NULL) previous_screen = gdk_screen_get_default (); @@ -975,7 +999,7 @@ gtk_font_chooser_widget_screen_changed (GtkWidget *widget, if (previous_screen == gtk_widget_get_screen (widget)) return; - gtk_font_chooser_widget_load_fonts (fontchooser); + gtk_font_chooser_widget_load_fonts (fontchooser, FALSE); } static void @@ -985,7 +1009,7 @@ gtk_font_chooser_widget_style_updated (GtkWidget *widget) GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->style_updated (widget); - gtk_font_chooser_widget_load_fonts (fontchooser); + gtk_font_chooser_widget_load_fonts (fontchooser, FALSE); } static PangoFontFamily * @@ -1161,7 +1185,6 @@ gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser, else { gtk_font_chooser_widget_merge_font_desc (fontchooser, font_desc, &priv->font_iter); - } } @@ -1214,6 +1237,28 @@ gtk_font_chooser_widget_set_show_preview_entry (GtkFontChooserWidget *fontchoose } } +static void +gtk_font_chooser_widget_set_font_map (GtkFontChooserWidget *fontchooser, + PangoFontMap *fontmap) +{ + GtkFontChooserWidgetPrivate *priv = fontchooser->priv; + + if (g_set_object (&priv->font_map, fontmap)) + { + PangoContext *context; + + if (!fontmap) + fontmap = pango_cairo_font_map_get_default (); + + context = gtk_widget_get_pango_context (priv->family_face_list); + pango_context_set_font_map (context, fontmap); + + gtk_font_chooser_widget_load_fonts (fontchooser, TRUE); + + g_object_notify (G_OBJECT (fontchooser), "font-map"); + } +} + static void gtk_font_chooser_widget_set_filter_func (GtkFontChooser *chooser, GtkFontFilterFunc filter, diff --git a/tests/testfontchooserdialog.c b/tests/testfontchooserdialog.c index 574b138b1c..2e2da14a37 100644 --- a/tests/testfontchooserdialog.c +++ b/tests/testfontchooserdialog.c @@ -16,6 +16,7 @@ */ #include +#include #include static gboolean @@ -71,8 +72,29 @@ main (int argc, char *argv[]) gtk_init (&argc, &argv); - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); font_button = gtk_font_button_new (); + + if (argc > 0) + { + FcConfig *config; + PangoFontMap *fontmap; + gint i; + + /* Create a custom font configuration by adding font files specified + * on the commandline to the default config. + */ + config = FcInitLoadConfigAndFonts (); + for (i = 0; i < argc; i++) + FcConfigAppFontAddFile (config, (const FcChar8 *)argv[i]); + + fontmap = pango_cairo_font_map_new_for_font_type (CAIRO_FONT_TYPE_FT); + pango_fc_font_map_set_config (PANGO_FC_FONT_MAP (fontmap), config); + gtk_font_chooser_set_font_map (GTK_FONT_CHOOSER (font_button), fontmap); + } + + gtk_font_button_set_use_font (GTK_FONT_BUTTON (font_button), TRUE); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_container_add (GTK_CONTAINER (window), font_button); gtk_widget_show_all (window);