[gtk+] GtkFontChooser: Allow a custom font map



commit 049cbc8b74aa7a6fff1627c8c65cbfd3c86dfde8
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon May 4 23:21:17 2015 -0400

    GtkFontChooser: Allow a custom font map
    
    This lets applications show their own fonts instead of
    or in addition to system fonts.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=748771

 docs/reference/gtk/gtk3-sections.txt |    2 +
 gtk/gtkfontbutton.c                  |   41 ++++++++++++++---
 gtk/gtkfontchooser.c                 |   56 +++++++++++++++++++++++
 gtk/gtkfontchooser.h                 |    5 ++
 gtk/gtkfontchooserutils.c            |    3 +
 gtk/gtkfontchooserutils.h            |    1 +
 gtk/gtkfontchooserwidget.c           |   81 ++++++++++++++++++++++++++--------
 tests/testfontchooserdialog.c        |   24 ++++++++++-
 8 files changed, 187 insertions(+), 26 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index 8f15a3a..4cd12c1 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
 
 <SUBSECTION Standard>
 GtkFontChooserIface
diff --git a/gtk/gtkfontbutton.c b/gtk/gtkfontbutton.c
index acaadda..492c4d2 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);
@@ -385,6 +386,24 @@ gtk_font_button_get_font_desc (GtkFontButton *font_button)
 }
 
 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,
                                      gpointer    user_data)
@@ -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 35591d2..370b1a3 100644
--- a/gtk/gtkfontchooser.c
+++ b/gtk/gtkfontchooser.c
@@ -107,6 +107,18 @@ gtk_font_chooser_default_init (GtkFontChooserInterface *iface)
                           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
    * @fontname: the font name
@@ -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 1c1bbf0..84693c1 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 5014883..ff8ca68 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 7c92a64..0a8f9f8 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 a991702..809e336 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);
 }
 
@@ -951,6 +969,12 @@ gtk_font_chooser_widget_find_font (GtkFontChooserWidget        *fontchooser,
 }
 
 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);
-                                                          
     }
 }
 
@@ -1215,6 +1238,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,
                                          gpointer          data,
diff --git a/tests/testfontchooserdialog.c b/tests/testfontchooserdialog.c
index 574b138..2e2da14 100644
--- a/tests/testfontchooserdialog.c
+++ b/tests/testfontchooserdialog.c
@@ -16,6 +16,7 @@
  */
 
 #include <string.h>
+#include <pango/pangofc-fontmap.h>
 #include <gtk/gtk.h>
 
 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);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]