[gtk+/wip/matthiasc/font-variations] wip:font variations
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/matthiasc/font-variations] wip:font variations
- Date: Thu, 17 Aug 2017 12:46:09 +0000 (UTC)
commit 091083ad2e2a97058de76c097ded5401912c7843
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Aug 16 23:48:52 2017 -0400
wip:font variations
demos/gtk-demo/font-features.ui | 34 +++++-
demos/gtk-demo/font_features.c | 255 +++++++++++++++++++++++++++++++++++++++
2 files changed, 288 insertions(+), 1 deletions(-)
---
diff --git a/demos/gtk-demo/font-features.ui b/demos/gtk-demo/font-features.ui
index 0bd2645..70f49ec 100644
--- a/demos/gtk-demo/font-features.ui
+++ b/demos/gtk-demo/font-features.ui
@@ -54,8 +54,16 @@
</object>
</child>
<child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Script & Language</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
<object class="GtkComboBox" id="script_lang">
- <property name="visible">1</property>
<property name="can_focus">1</property>
<signal name="changed" handler="script_changed" swapped="no"/>
<child>
@@ -67,6 +75,15 @@
</object>
</child>
<child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Features</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
<object class="GtkExpander">
<property name="visible">1</property>
<property name="can_focus">1</property>
@@ -1580,6 +1597,21 @@
</child>
</object>
</child>
+ <child>
+ <object class="GtkLabel" id="variations_heading">
+ <property name="label" translatable="yes">Variations</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="variations_grid">
+ <property name="column-spacing">6</property>
+ <property name="row-spacing">6</property>
+ </object>
+ </child>
</object>
</child>
<style>
diff --git a/demos/gtk-demo/font_features.c b/demos/gtk-demo/font_features.c
index 761bf8f..573e98c 100644
--- a/demos/gtk-demo/font_features.c
+++ b/demos/gtk-demo/font_features.c
@@ -13,6 +13,8 @@
#include <hb.h>
#include <hb-ot.h>
#include <hb-ft.h>
+#include <freetype/ftmm.h>
+#include <freetype/ftsnames.h>
static GtkWidget *label;
static GtkWidget *settings;
@@ -24,6 +26,9 @@ static GtkWidget *numspacedefault;
static GtkWidget *fractiondefault;
static GtkWidget *stack;
static GtkWidget *entry;
+static GtkWidget *variations_heading;
+static GtkWidget *variations_grid;
+static GtkWidget *instance_combo;
#define num_features 40
@@ -404,10 +409,253 @@ update_features (void)
g_object_unref (pango_font);
}
+#define FixedToFloat(f) (((float)(f))/65536)
+
+static void
+adjustment_changed (GtkAdjustment *adjustment,
+ GtkEntry *entry)
+{
+ char *str;
+
+ str = g_strdup_printf ("%g", gtk_adjustment_get_value (adjustment));
+ gtk_entry_set_text (GTK_ENTRY (entry), str);
+ g_free (str);
+}
+
+static void
+entry_activated (GtkEntry *entry,
+ GtkAdjustment *adjustment)
+{
+ gdouble value;
+ gchar *err = NULL;
+
+ value = g_strtod (gtk_entry_get_text (entry), &err);
+ if (err != NULL)
+ gtk_adjustment_set_value (adjustment, value);
+}
+
+typedef struct {
+ guint32 tag;
+ GtkAdjustment *adjustment;
+} Axis;
+
+static GHashTable *axes;
+
+static void unset_instance (GtkAdjustment *adjustment);
+
+static void
+add_axis (FT_Var_Axis *ax, int i)
+{
+ GtkWidget *label;
+ GtkAdjustment *adjustment;
+ GtkWidget *scale;
+ Axis *axis;
+
+ label = gtk_label_new (ax->name);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
+ gtk_grid_attach (GTK_GRID (variations_grid), label, 0, i, 1, 1);
+ adjustment = gtk_adjustment_new ((double)FixedToFloat(ax->def),
+ (double)FixedToFloat(ax->minimum),
+ (double)FixedToFloat(ax->maximum),
+ 1.0, 10.0, 0.0);
+ scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adjustment);
+ gtk_scale_add_mark (GTK_SCALE (scale), (double)FixedToFloat(ax->def), GTK_POS_TOP, NULL);
+ gtk_widget_set_valign (scale, GTK_ALIGN_BASELINE);
+ gtk_widget_set_hexpand (scale, TRUE);
+ gtk_widget_set_size_request (scale, 100, -1);
+ gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
+ gtk_grid_attach (GTK_GRID (variations_grid), scale, 1, i, 1, 1);
+ entry = gtk_entry_new ();
+ gtk_widget_set_valign (entry, GTK_ALIGN_BASELINE);
+ gtk_entry_set_width_chars (GTK_ENTRY (entry), 4);
+ gtk_grid_attach (GTK_GRID (variations_grid), entry, 2, i, 1, 1);
+
+ axis = g_new (Axis, 1);
+ axis->tag = ax->tag;
+ axis->adjustment = adjustment;
+ g_hash_table_insert (axes, &axis->tag, axis);
+
+ adjustment_changed (adjustment, GTK_ENTRY (entry));
+
+ g_signal_connect (adjustment, "value-changed", G_CALLBACK (adjustment_changed), entry);
+ g_signal_connect (adjustment, "value-changed", G_CALLBACK (unset_instance), NULL);
+ g_signal_connect (entry, "activate", G_CALLBACK (entry_activated), adjustment);
+}
+
+typedef struct {
+ char *name;
+ int n_axes;
+ guint32 *axes;
+ float *coords;
+} Instance;
+
+static void
+free_instance (gpointer data)
+{
+ Instance *instance = data;
+
+ g_free (instance->name);
+ g_free (instance->axes);
+ g_free (instance->coords);
+ g_free (instance);
+}
+
+static GHashTable *instances;
+
+static void
+add_instance (FT_Face ft_face,
+ FT_MM_Var *ft_mm_var,
+ FT_Var_Named_Style *ns,
+ GtkWidget *combo)
+{
+ FT_SfntName ft_name;
+ Instance *instance;
+ int i;
+
+ instance = g_new0 (Instance, 1);
+
+ if (FT_Get_Sfnt_Name (ft_face, ns->strid, &ft_name) == 0)
+ instance->name = g_strndup ((char *)ft_name.string, ft_name.string_len);
+ else
+ instance->name = g_strdup_printf ("%u", ns->strid);
+
+ g_hash_table_insert (instances, instance->name, instance);
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), instance->name);
+
+ instance->n_axes = ft_mm_var->num_axis;
+ instance->axes = g_new (guint32, ft_mm_var->num_axis);
+ instance->coords = g_new (float, ft_mm_var->num_axis);
+
+ for (i = 0; i < ft_mm_var->num_axis; i++)
+ {
+ instance->axes[i] = ft_mm_var->axis[i].tag;
+ instance->coords[i] = FixedToFloat(ns->coords[i]);
+ }
+}
+
+static void
+unset_instance (GtkAdjustment *adjustment)
+{
+ if (instance_combo)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (instance_combo), 0);
+}
+
+static void
+instance_changed (GtkComboBox *combo)
+{
+ char *text;
+ Instance *instance;
+ int i;
+
+ text = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo));
+ if (text[0] == '\0')
+ goto out;
+
+ instance = g_hash_table_lookup (instances, text);
+ if (!instance)
+ {
+ g_print ("did not find instance %s\n", text);
+ goto out;
+ }
+
+ for (i = 0; i < instance->n_axes; i++)
+ {
+ Axis *axis;
+ guint32 tag;
+ gdouble value;
+
+ tag = instance->axes[i];
+ value = instance->coords[i];
+
+ axis = g_hash_table_lookup (axes, &tag);
+ if (axis)
+ {
+ g_signal_handlers_block_by_func (axis->adjustment, unset_instance, NULL);
+ gtk_adjustment_set_value (axis->adjustment, value);
+ g_signal_handlers_unblock_by_func (axis->adjustment, unset_instance, NULL);
+ }
+ }
+
+out:
+ g_free (text);
+}
+
+static void
+update_font_variations (void)
+{
+ GtkWidget *child, *next;
+ PangoFont *pango_font;
+ FT_Face ft_face;
+ FT_MM_Var *ft_mm_var;
+ FT_Error ret;
+
+ child = gtk_widget_get_first_child (variations_grid);
+ while (child != NULL)
+ {
+ next = gtk_widget_get_next_sibling (child);
+ gtk_widget_destroy (child);
+ child = next;
+ }
+
+ instance_combo = NULL;
+
+ g_hash_table_remove_all (axes);
+ g_hash_table_remove_all (instances);
+
+ pango_font = get_pango_font ();
+ ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font)),
+
+ ret = FT_Get_MM_Var (ft_face, &ft_mm_var);
+ if (ret == 0)
+ {
+ unsigned int i;
+
+ gtk_widget_show (variations_heading);
+
+ if (ft_mm_var->num_namedstyles > 0)
+ {
+ GtkWidget *label;
+ GtkWidget *combo;
+
+ label = gtk_label_new ("Instance");
+ gtk_label_set_xalign (GTK_LABEL (label), 0);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
+ gtk_grid_attach (GTK_GRID (variations_grid), label, 0, -1, 2, 1);
+
+ combo = gtk_combo_box_text_new ();
+ gtk_widget_set_valign (combo, GTK_ALIGN_BASELINE);
+ g_signal_connect (combo, "changed", G_CALLBACK (instance_changed), NULL);
+ gtk_grid_attach (GTK_GRID (variations_grid), combo, 1, -1, 2, 1);
+
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "");
+
+ for (i = 0; i < ft_mm_var->num_namedstyles; i++)
+ add_instance (ft_face, ft_mm_var, &ft_mm_var->namedstyle[i], combo);
+
+ instance_combo = combo;
+ }
+
+ for (i = 0; i < ft_mm_var->num_axis; i++)
+ add_axis (&ft_mm_var->axis[i], i);
+
+ free (ft_mm_var);
+ }
+ else
+ {
+ gtk_widget_hide (variations_heading);
+ }
+
+ pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+ g_object_unref (pango_font);
+}
+
static void
font_changed (void)
{
update_script_combo ();
+ update_font_variations ();
}
static void
@@ -509,6 +757,13 @@ do_font_features (GtkWidget *do_widget)
g_free (iname);
}
+ variations_heading = GTK_WIDGET (gtk_builder_get_object (builder, "variations_heading"));
+ variations_grid = GTK_WIDGET (gtk_builder_get_object (builder, "variations_grid"));
+ if (instances == NULL)
+ instances = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_instance);
+ if (axes == NULL)
+ axes = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, g_free);
+
font_changed ();
g_signal_connect (window, "destroy",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]