summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2017-12-30 18:20:25 -0500
committerMatthias Clasen <mclasen@redhat.com>2017-12-30 18:34:17 -0500
commita33cecde955e7dda309413656885e598a5e44839 (patch)
treed0c814e6fb5c61585bc8d0f6ff47c90195fd6c7b
parent5625155755b46720e6dad7f949f43620595a2725 (diff)
downloadgtk+-wip/matthiasc/font-variations.tar.gz
gtk-demo: Revise the font features demo some morewip/matthiasc/font-variations
Make it so that you can tweak ranges.
-rw-r--r--demos/gtk-demo/font-features.ui1
-rw-r--r--demos/gtk-demo/font_features.c210
2 files changed, 170 insertions, 41 deletions
diff --git a/demos/gtk-demo/font-features.ui b/demos/gtk-demo/font-features.ui
index 6ddd98fb90..c7024491c3 100644
--- a/demos/gtk-demo/font-features.ui
+++ b/demos/gtk-demo/font-features.ui
@@ -134,6 +134,7 @@
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="valign">start</property>
+ <property name="selectable">1</property>
</object>
<packing>
<property name="name">label</property>
diff --git a/demos/gtk-demo/font_features.c b/demos/gtk-demo/font_features.c
index 9b70f6085e..dd69f0b1df 100644
--- a/demos/gtk-demo/font_features.c
+++ b/demos/gtk-demo/font_features.c
@@ -52,8 +52,84 @@ typedef struct {
static GList *feature_items;
+typedef struct {
+ unsigned int start;
+ unsigned int end;
+ PangoFontDescription *desc;
+ char *features;
+ PangoLanguage *language;
+} Range;
+
+static GList *ranges;
+
static void add_font_variations (GString *s);
+static void
+free_range (gpointer data)
+{
+ Range *range = data;
+
+ if (range->desc)
+ pango_font_description_free (range->desc);
+ g_free (range->features);
+ g_free (range);
+}
+
+static int
+compare_range (gconstpointer a, gconstpointer b)
+{
+ const Range *ra = a;
+ const Range *rb = b;
+
+ if (ra->start < rb->start)
+ return -1;
+ else if (ra->start > rb->start)
+ return 1;
+ else if (ra->end < rb->end)
+ return 1;
+ else if (ra->end > rb->end)
+ return -1;
+
+ return 0;
+}
+
+static void
+ensure_range (unsigned int start,
+ unsigned int end,
+ PangoFontDescription *desc,
+ const char *features,
+ PangoLanguage *language)
+{
+ GList *l;
+ Range *range;
+
+ for (l = ranges; l; l = l->next)
+ {
+ Range *r = l->data;
+
+ if (r->start == start && r->end == end)
+ {
+ range = r;
+ goto set;
+ }
+ }
+
+ range = g_new0 (Range, 1);
+ range->start = start;
+ range->end = end;
+
+ ranges = g_list_insert_sorted (ranges, range, compare_range);
+
+set:
+ if (range->desc)
+ pango_font_description_free (range->desc);
+ if (desc)
+ range->desc = pango_font_description_copy (desc);
+ g_free (range->features);
+ range->features = g_strdup (features);
+ range->language = language;
+}
+
static const char *
get_feature_display_name (unsigned int tag)
{
@@ -71,6 +147,14 @@ get_feature_display_name (unsigned int tag)
static void update_display (void);
static void
+set_inconsistent (GtkCheckButton *button,
+ gboolean inconsistent)
+{
+ gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (button), inconsistent);
+ gtk_widget_set_opacity (gtk_widget_get_first_child (GTK_WIDGET (button)), inconsistent ? 0.0 : 1.0);
+}
+
+static void
feat_clicked (GtkWidget *feat,
gpointer data)
{
@@ -78,8 +162,7 @@ feat_clicked (GtkWidget *feat,
if (gtk_check_button_get_inconsistent (GTK_CHECK_BUTTON (feat)))
{
- gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (feat), FALSE);
- gtk_widget_set_opacity (gtk_widget_get_first_child (feat), 1);
+ set_inconsistent (GTK_CHECK_BUTTON (feat), FALSE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (feat), TRUE);
}
else if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (feat)))
@@ -88,8 +171,7 @@ feat_clicked (GtkWidget *feat,
}
else
{
- gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (feat), TRUE);
- gtk_widget_set_opacity (gtk_widget_get_first_child (feat), 0);
+ set_inconsistent (GTK_CHECK_BUTTON (feat), TRUE);
}
g_signal_handlers_unblock_by_func (feat, feat_clicked, NULL);
@@ -127,8 +209,7 @@ add_check_group (GtkWidget *box,
tag = hb_tag_from_string (tags[i], -1);
feat = gtk_check_button_new_with_label (get_feature_display_name (tag));
- gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (feat), TRUE);
- gtk_widget_set_opacity (gtk_widget_get_first_child (feat), 0);
+ set_inconsistent (GTK_CHECK_BUTTON (feat), TRUE);
g_signal_connect (feat, "notify::active", G_CALLBACK (update_display), NULL);
g_signal_connect (feat, "notify::inconsistent", G_CALLBACK (update_display), NULL);
@@ -210,33 +291,44 @@ static void
update_display (void)
{
GString *s;
- char *font_desc;
- char *font_settings;
const char *text;
gboolean has_feature;
- hb_tag_t lang_tag;
- GtkTreeModel *model;
GtkTreeIter iter;
- const char *lang;
+ GtkTreeModel *model;
PangoFontDescription *desc;
- char *tmp;
GList *l;
+ PangoAttrList *attrs;
+ PangoAttribute *attr;
+ gint ins, bound;
+ guint start, end;
+ PangoLanguage *lang;
+ char *font_desc;
+ char *features;
text = gtk_entry_get_text (GTK_ENTRY (entry));
- desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (font));
- pango_font_description_unset_fields (desc, PANGO_FONT_MASK_VARIATIONS);
- tmp = pango_font_description_to_string (desc);
-
- s = g_string_new (tmp);
+ if (gtk_label_get_selection_bounds (GTK_LABEL (label), &ins, &bound))
+ {
+ start = g_utf8_offset_to_pointer (text, ins) - text;
+ end = g_utf8_offset_to_pointer (text, bound) - text;
+ }
+ else
+ {
+ start = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING;
+ end = PANGO_ATTR_INDEX_TO_TEXT_END;
+ }
- g_free (tmp);
- pango_font_description_free (desc);
+ desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (font));
+ s = g_string_new ("");
add_font_variations (s);
- font_desc = g_string_free (s, FALSE);
+ if (s->len > 0)
+ {
+ pango_font_description_set_variations (desc, s->str);
+ g_string_free (s, TRUE);
+ }
- gtk_label_set_text (GTK_LABEL (description), font_desc);
+ font_desc = pango_font_description_to_string (desc);
s = g_string_new ("");
@@ -276,34 +368,58 @@ update_display (void)
}
}
- font_settings = g_string_free (s, FALSE);
-
- gtk_label_set_text (GTK_LABEL (settings), font_settings);
+ features = g_string_free (s, FALSE);
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (script_lang), &iter))
{
+ hb_tag_t lang_tag;
+
model = gtk_combo_box_get_model (GTK_COMBO_BOX (script_lang));
gtk_tree_model_get (model, &iter,
3, &lang_tag,
-1);
- lang = hb_language_to_string (hb_ot_tag_to_language (lang_tag));
+ lang = pango_language_from_string (hb_language_to_string (hb_ot_tag_to_language (lang_tag)));
}
else
lang = NULL;
- s = g_string_new ("");
- g_string_append_printf (s, "<span font_desc='%s' font_features='%s'", font_desc, font_settings);
- if (lang)
- g_string_append_printf (s, " lang='%s'", lang);
- g_string_append_printf (s, ">%s</span>", text);
+ ensure_range (start, end, desc, features, lang);
+
+ attrs = pango_attr_list_new ();
+
+ for (l = ranges; l; l = l->next)
+ {
+ Range *range = l->data;
+
+ attr = pango_attr_font_desc_new (range->desc);
+ attr->start_index = range->start;
+ attr->end_index = range->end;
+ pango_attr_list_insert (attrs, attr);
- gtk_label_set_markup (GTK_LABEL (label), s->str);
+ attr = pango_attr_font_features_new (range->features);
+ attr->start_index = range->start;
+ attr->end_index = range->end;
+ pango_attr_list_insert (attrs, attr);
- g_string_free (s, TRUE);
+ if (range->language)
+ {
+ attr = pango_attr_language_new (range->language);
+ attr->start_index = range->start;
+ attr->end_index = range->end;
+ pango_attr_list_insert (attrs, attr);
+ }
+ }
+
+ gtk_label_set_text (GTK_LABEL (description), font_desc);
+ gtk_label_set_text (GTK_LABEL (settings), features);
+ gtk_label_set_text (GTK_LABEL (label), text);
+ gtk_label_set_attributes (GTK_LABEL (label), attrs);
g_free (font_desc);
- g_free (font_settings);
+ pango_font_description_free (desc);
+ g_free (features);
+ pango_attr_list_unref (attrs);
}
static PangoFont *
@@ -538,6 +654,12 @@ update_features (void)
for (j = 0; j < count; j++)
{
+#if 0
+ char buf[5];
+ hb_tag_to_string (features[j], buf);
+ buf[4] = 0;
+ g_print ("%s present in %s\n", buf, i == 0 ? "GSUB" : "GPOS");
+#endif
for (l = feature_items; l; l = l->next)
{
FeatureItem *item = l->data;
@@ -553,8 +675,7 @@ update_features (void)
}
else if (GTK_IS_CHECK_BUTTON (item->feat))
{
- gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (item->feat), TRUE);
- gtk_widget_set_opacity (gtk_widget_get_first_child (item->feat), 0);
+ set_inconsistent (GTK_CHECK_BUTTON (item->feat), TRUE);
}
}
}
@@ -582,8 +703,7 @@ update_features (void)
}
else if (GTK_IS_CHECK_BUTTON (item->feat))
{
- gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (item->feat), FALSE);
- gtk_widget_set_opacity (gtk_widget_get_first_child (item->feat), 1);
+ set_inconsistent (GTK_CHECK_BUTTON (item->feat), FALSE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), p[5] == '1');
}
}
@@ -641,7 +761,7 @@ add_font_variations (GString *s)
GHashTableIter iter;
Axis *axis;
char buf[G_ASCII_DTOSTR_BUF_SIZE];
- char *sep = " @";
+ char *sep = "";
g_hash_table_iter_init (&iter, axes);
while (g_hash_table_iter_next (&iter, (gpointer *)NULL, (gpointer *)&axis))
@@ -1492,16 +1612,24 @@ reset_features (void)
{
GList *l;
+ gtk_label_select_region (GTK_LABEL (label), 0, 0);
+
+ g_list_free_full (ranges, free_range);
+ ranges = NULL;
+
for (l = feature_items; l; l = l->next)
{
FeatureItem *item = l->data;
- if (strcmp (item->name, "xxxx") == 0)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), TRUE);
+ if (GTK_IS_RADIO_BUTTON (item->feat))
+ {
+ if (strcmp (item->name, "xxxx") == 0)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), TRUE);
+ }
else if (GTK_IS_CHECK_BUTTON (item->feat))
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), FALSE);
- gtk_widget_set_sensitive (item->feat, FALSE);
+ set_inconsistent (GTK_CHECK_BUTTON (item->feat), TRUE);
}
}
}