summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-08-25 22:26:07 -0400
committerMatthias Clasen <mclasen@redhat.com>2022-08-26 17:53:55 -0400
commit0441fd367866c8ab7aa3d7646adddbcf93ac50e6 (patch)
tree0693ae7d5aebb92a57f9c339355f116f61b9e0d5
parent2017f3debee788b993363b1ed0fcce8629f2560c (diff)
downloadgtk+-0441fd367866c8ab7aa3d7646adddbcf93ac50e6.tar.gz
fontchooser: Handle font features better
Properly show multiple-choice cvXX features as dropdowns, include afrc, and fix bugs in feature enumeration that made some features not show up.
-rw-r--r--gtk/gtkfontchooserwidget.c468
1 files changed, 369 insertions, 99 deletions
diff --git a/gtk/gtkfontchooserwidget.c b/gtk/gtkfontchooserwidget.c
index 37967788d7..4a600878a9 100644
--- a/gtk/gtkfontchooserwidget.c
+++ b/gtk/gtkfontchooserwidget.c
@@ -62,6 +62,7 @@
#include "gtklistview.h"
#include "gtksortlistmodel.h"
#include "gtkstringsorter.h"
+#include "gtkdropdown.h"
#include <hb-ot.h>
@@ -1882,76 +1883,114 @@ find_affected_text (GtkFontChooserWidget *fontchooser,
{
unsigned int lookup_indexes[32];
unsigned int lookup_count = 32;
- int count;
+ unsigned int count;
int n_chars = 0;
- count = hb_ot_layout_feature_get_lookups (hb_face,
- HB_OT_TAG_GSUB,
- feature_index,
- 0,
- &lookup_count,
- lookup_indexes);
+ count = hb_ot_layout_feature_get_characters (hb_face,
+ HB_OT_TAG_GSUB,
+ feature_index,
+ 0,
+ NULL, NULL);
if (count > 0)
{
- hb_set_t *glyphs_before = NULL;
- hb_set_t *glyphs_after = NULL;
- hb_set_t *glyphs_output = NULL;
- hb_set_t *glyphs_input;
- hb_codepoint_t gid;
- char buf[5] = { 0, };
-
- hb_tag_to_string (feature_tag, buf);
+ hb_codepoint_t *ch;
+
+ ch = g_alloca (sizeof (hb_codepoint_t) * count);
+ hb_ot_layout_feature_get_characters (hb_face,
+ HB_OT_TAG_GSUB,
+ feature_index,
+ 0,
+ &count,
+ ch);
+
+ for (unsigned int i = 0; i < MIN (count, max_chars); i++)
+ g_string_append_unichar (chars, ch[i]);
+ }
+ else
+ {
+ count = hb_ot_layout_feature_get_lookups (hb_face,
+ HB_OT_TAG_GSUB,
+ feature_index,
+ 0,
+ &lookup_count,
+ lookup_indexes);
+ if (count > 0)
+ {
+ hb_set_t *glyphs_before = NULL;
+ hb_set_t *glyphs_after = NULL;
+ hb_set_t *glyphs_output = NULL;
+ hb_set_t *glyphs_input;
+ hb_codepoint_t gid;
+ char buf[5] = { 0, };
- glyphs_input = hb_set_create ();
+ hb_tag_to_string (feature_tag, buf);
- for (int i = 0; i < count; i++)
- {
- hb_ot_layout_lookup_collect_glyphs (hb_face,
- HB_OT_TAG_GSUB,
- lookup_indexes[i],
- glyphs_before,
- glyphs_input,
- glyphs_after,
- glyphs_output);
- }
+ glyphs_input = hb_set_create ();
- if (!fontchooser->glyphmap)
- {
- fontchooser->glyphmap = hb_map_create ();
- for (hb_codepoint_t ch = 0; ch < 0xffff; ch++)
+ for (int i = 0; i < count; i++)
{
- hb_codepoint_t glyph = 0;
- if (hb_font_get_nominal_glyph (hb_font, ch, &glyph) &&
- !hb_map_has (fontchooser->glyphmap, glyph))
- hb_map_set (fontchooser->glyphmap, glyph, ch);
+ hb_ot_layout_lookup_collect_glyphs (hb_face,
+ HB_OT_TAG_GSUB,
+ lookup_indexes[i],
+ glyphs_before,
+ glyphs_input,
+ glyphs_after,
+ glyphs_output);
}
- }
- gid = HB_SET_VALUE_INVALID;
- while (hb_set_next (glyphs_input, &gid))
- {
- hb_codepoint_t ch;
-
- if (n_chars == max_chars)
+ if (!fontchooser->glyphmap)
{
- g_string_append (chars, "…");
- break;
+ fontchooser->glyphmap = hb_map_create ();
+ for (hb_codepoint_t ch = 0; ch < 0xffff; ch++)
+ {
+ hb_codepoint_t glyph = 0;
+ if (hb_font_get_nominal_glyph (hb_font, ch, &glyph) &&
+ !hb_map_has (fontchooser->glyphmap, glyph))
+ hb_map_set (fontchooser->glyphmap, glyph, ch);
+ }
}
- ch = hb_map_get (fontchooser->glyphmap, gid);
- if (ch != HB_MAP_VALUE_INVALID)
+
+ gid = HB_SET_VALUE_INVALID;
+ while (hb_set_next (glyphs_input, &gid))
{
- g_string_append_unichar (chars, (gunichar)ch);
- n_chars++;
+ hb_codepoint_t ch;
+
+ if (n_chars == max_chars)
+ {
+ g_string_append (chars, "…");
+ break;
+ }
+ ch = hb_map_get (fontchooser->glyphmap, gid);
+ if (ch != HB_MAP_VALUE_INVALID)
+ {
+ g_string_append_unichar (chars, (gunichar)ch);
+ n_chars++;
+ }
}
- }
- hb_set_destroy (glyphs_input);
+ hb_set_destroy (glyphs_input);
+ }
}
}
return g_string_free (chars, FALSE);
}
+static char *
+get_name (hb_face_t *hb_face,
+ hb_ot_name_id_t id)
+{
+ unsigned int len;
+ char *name;
+
+ len = hb_ot_name_get_utf8 (hb_face, id, HB_LANGUAGE_INVALID, NULL, NULL);
+ len++;
+ name = g_new (char, len);
+ hb_ot_name_get_utf8 (hb_face, id, HB_LANGUAGE_INVALID, &len, name);
+
+ return name;
+}
+
static void
update_feature_label (GtkFontChooserWidget *fontchooser,
FeatureItem *item,
@@ -1961,9 +2000,8 @@ update_feature_label (GtkFontChooserWidget *fontchooser,
{
hb_face_t *hb_face;
unsigned int script_index, lang_index, feature_index;
- hb_ot_name_id_t id;
- unsigned int len;
- char *label;
+ hb_ot_name_id_t label_id, first_param_id;
+ unsigned int num_params;
hb_face = hb_font_get_face (hb_font);
@@ -1978,22 +2016,106 @@ update_feature_label (GtkFontChooserWidget *fontchooser,
G_GNUC_END_IGNORE_DEPRECATIONS
if (hb_ot_layout_language_find_feature (hb_face, HB_OT_TAG_GSUB, script_index, lang_index, item->tag, &feature_index) &&
- hb_ot_layout_feature_get_name_ids (hb_face, HB_OT_TAG_GSUB, feature_index, &id, NULL, NULL, NULL, NULL))
+ hb_ot_layout_feature_get_name_ids (hb_face, HB_OT_TAG_GSUB, feature_index, &label_id, NULL, NULL, &num_params, &first_param_id))
{
- len = hb_ot_name_get_utf8 (hb_face, id, HB_LANGUAGE_INVALID, NULL, NULL);
- len++;
- label = g_new (char, len);
- hb_ot_name_get_utf8 (hb_face, id, HB_LANGUAGE_INVALID, &len, label);
+ if (label_id != HB_OT_NAME_ID_INVALID)
+ {
+ char *label = get_name (hb_face, label_id);
+ if (GTK_IS_CHECK_BUTTON (item->feat))
+ gtk_check_button_set_label (GTK_CHECK_BUTTON (item->feat), label);
+ else
+ {
+ GtkWidget *l = gtk_widget_get_prev_sibling (item->feat);
+ gtk_label_set_label (GTK_LABEL (l), label);
+ }
+ g_free (label);
+ }
+ else
+ {
+ if (GTK_IS_CHECK_BUTTON (item->feat))
+ gtk_check_button_set_label (GTK_CHECK_BUTTON (item->feat), item->name);
+ else
+ {
+ GtkWidget *l = gtk_widget_get_prev_sibling (item->feat);
+ gtk_label_set_label (GTK_LABEL (l), item->name);
+ }
+ }
- char *s = g_strdup_printf ("%s (%s)", label, item->name);
- gtk_check_button_set_label (GTK_CHECK_BUTTON (item->feat), s);
- g_free (s);
+ if (GTK_IS_DROP_DOWN (item->feat))
+ {
+ unsigned int n_lookups;
+ GtkStringList *strings;
+ unsigned int *lookups;
+ unsigned int n_alternates;
+
+ n_lookups = hb_ot_layout_feature_get_lookups (hb_face,
+ HB_OT_TAG_GSUB,
+ feature_index,
+ 0,
+ NULL, NULL);
+
+ lookups = g_alloca (sizeof (unsigned int) * n_lookups);
+ hb_ot_layout_feature_get_lookups (hb_face,
+ HB_OT_TAG_GSUB,
+ feature_index,
+ 0,
+ &n_lookups,
+ lookups);
+
+ n_alternates = 0;
+ for (unsigned int l = 0; l < n_lookups; l++)
+ {
+ hb_set_t *glyphs;
+ hb_codepoint_t glyph_index;
+ unsigned int lookup = lookups[l];
- g_free (label);
+ glyphs = hb_set_create ();
+
+ hb_ot_layout_lookup_collect_glyphs (hb_face,
+ HB_OT_TAG_GSUB,
+ lookup,
+ NULL,
+ glyphs,
+ NULL, NULL);
+
+ glyph_index = HB_SET_VALUE_INVALID;
+ while (hb_set_next (glyphs, &glyph_index))
+ n_alternates = MAX (n_alternates,
+ hb_ot_layout_lookup_get_glyph_alternates (hb_face,
+ lookup,
+ glyph_index,
+ 0, NULL, NULL));
+
+ hb_set_destroy (glyphs);
+ }
+
+ strings = gtk_string_list_new (NULL);
+ gtk_string_list_append (strings, C_("Font feature value", "None"));
+ for (unsigned int i = 0; i < num_params; i++)
+ {
+ char *name;
+ name = get_name (hb_face, first_param_id + i);
+ gtk_string_list_append (strings, name);
+ g_free (name);
+ }
+
+ for (int i = num_params; i < n_alternates; i++)
+ {
+ char buf[64];
+ g_snprintf (buf, sizeof (buf), "%d", i + 1);
+ gtk_string_list_append (strings, buf);
+ }
+
+ if (g_list_model_get_n_items (G_LIST_MODEL (strings)) == 1)
+ gtk_string_list_append (strings, C_("Font feature value", "Enable"));
+
+ gtk_drop_down_set_model (GTK_DROP_DOWN (item->feat), G_LIST_MODEL (strings));
+ g_object_unref (strings);
+ }
}
else
{
- label = get_feature_display_name (item->tag);
+ char *label = get_feature_display_name (item->tag);
gtk_check_button_set_label (GTK_CHECK_BUTTON (item->feat), label);
g_free (label);
}
@@ -2010,15 +2132,27 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
const char *letter_case[] = { "smcp", "c2sc", "pcap", "c2pc", "unic", "cpsp", "case", NULL };
const char *number_case[] = { "xxxx", "lnum", "onum", NULL };
const char *number_spacing[] = { "xxxx", "pnum", "tnum", NULL };
- const char *number_formatting[] = { "zero", "nalt", "frac", NULL };
+ const char *fraction[] = { "xxxx", "frac", "afrc", NULL };
const char *char_variants[] = {
+ "zero", "nalt",
"swsh", "cswh", "calt", "falt", "hist", "salt", "jalt", "titl", "rand",
"ss01", "ss02", "ss03", "ss04", "ss05", "ss06", "ss07", "ss08", "ss09", "ss10",
"ss11", "ss12", "ss13", "ss14", "ss15", "ss16", "ss17", "ss18", "ss19", "ss20",
+ "cv01", "cv02", "cv03", "cv04", "cv05", "cv06", "cv07", "cv08", "cv09", "cv10",
+ "cv11", "cv12", "cv13", "cv14", "cv15", "cv16", "cv17", "cv18", "cv19", "cv20",
+ "cv21", "cv22", "cv23", "cv24", "cv25", "cv26", "cv27", "cv28", "cv29", "cv30",
+ "cv31", "cv32", "cv33", "cv34", "cv35", "cv36", "cv37", "cv38", "cv39", "cv40",
+ "cv41", "cv42", "cv43", "cv44", "cv45", "cv46", "cv47", "cv48", "cv49", "cv50",
+ "cv51", "cv52", "cv53", "cv54", "cv55", "cv56", "cv57", "cv58", "cv59", "cv60",
+ "cv61", "cv62", "cv63", "cv64", "cv65", "cv66", "cv67", "cv68", "cv69", "cv70",
+ "cv71", "cv72", "cv73", "cv74", "cv75", "cv76", "cv77", "cv78", "cv79", "cv80",
+ "cv81", "cv82", "cv83", "cv84", "cv85", "cv86", "cv87", "cv88", "cv89", "cv90",
+ "cv91", "cv92", "cv93", "cv94", "cv95", "cv96", "cv97", "cv98", "cv99",
NULL };
if (g_strv_contains (number_case, item->name) ||
- g_strv_contains (number_spacing, item->name))
+ g_strv_contains (number_spacing, item->name) ||
+ g_strv_contains (fraction, item->name))
{
PangoAttrList *attrs;
PangoAttribute *attr;
@@ -2035,13 +2169,15 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
attr = pango_attr_font_features_new (str);
pango_attr_list_insert (attrs, attr);
- gtk_label_set_text (GTK_LABEL (item->example), "0123456789");
+ if (g_strv_contains (fraction, item->name))
+ gtk_label_set_text (GTK_LABEL (item->example), "1/2 2/3 7/8");
+ else
+ gtk_label_set_text (GTK_LABEL (item->example), "0123456789");
gtk_label_set_attributes (GTK_LABEL (item->example), attrs);
pango_attr_list_unref (attrs);
}
else if (g_strv_contains (letter_case, item->name) ||
- g_strv_contains (number_formatting, item->name) ||
g_strv_contains (char_variants, item->name))
{
char *input = NULL;
@@ -2053,8 +2189,6 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
input = g_strdup ("AaBbCc…");
else if (strcmp (item->name, "zero") == 0)
input = g_strdup ("0");
- else if (strcmp (item->name, "frac") == 0)
- input = g_strdup ("1/2 2/3 7/8");
else if (strcmp (item->name, "nalt") == 0)
input = find_affected_text (fontchooser, item->tag, hb_font, script_tag, lang_tag, 3);
else
@@ -2067,7 +2201,7 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
PangoFontDescription *desc;
char *str;
- text = g_strconcat (input, " ⟶ ", input, NULL);
+ text = g_strconcat (input, " → ", input, NULL);
attrs = pango_attr_list_new ();
@@ -2080,9 +2214,17 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
attr->start_index = 0;
attr->end_index = strlen (input);
pango_attr_list_insert (attrs, attr);
+ attr = pango_attr_fallback_new (FALSE);
+ attr->start_index = 0;
+ attr->end_index = strlen (input);
+ pango_attr_list_insert (attrs, attr);
str = g_strconcat (item->name, " 1", NULL);
attr = pango_attr_font_features_new (str);
- attr->start_index = strlen (input) + strlen (" ⟶ ");
+ attr->start_index = strlen (input) + strlen (" → ");
+ attr->end_index = attr->start_index + strlen (input);
+ pango_attr_list_insert (attrs, attr);
+ attr = pango_attr_fallback_new (FALSE);
+ attr->start_index = strlen (input) + strlen (" → ");
attr->end_index = attr->start_index + strlen (input);
pango_attr_list_insert (attrs, attr);
@@ -2109,9 +2251,10 @@ font_feature_toggled_cb (GtkCheckButton *check_button,
}
static void
-add_check_group (GtkFontChooserWidget *fontchooser,
- const char *title,
- const char **tags)
+add_check_group (GtkFontChooserWidget *fontchooser,
+ const char *title,
+ const char **tags,
+ unsigned int n_tags)
{
GtkWidget *label;
GtkWidget *group;
@@ -2131,7 +2274,7 @@ add_check_group (GtkFontChooserWidget *fontchooser,
pango_attr_list_unref (attrs);
gtk_box_append (GTK_BOX (group), label);
- for (i = 0; tags[i]; i++)
+ for (i = 0; i < n_tags; i++)
{
hb_tag_t tag;
GtkWidget *feat;
@@ -2179,9 +2322,87 @@ add_check_group (GtkFontChooserWidget *fontchooser,
}
static void
-add_radio_group (GtkFontChooserWidget *fontchooser,
- const char *title,
- const char **tags)
+font_enum_feature_changed_cb (GObject *object,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ GtkFontChooserWidget *fontchooser = data;
+
+ update_font_features (fontchooser);
+}
+
+static void
+add_enum_group (GtkFontChooserWidget *fontchooser,
+ const char *title,
+ const char **tags,
+ unsigned int n_tags)
+{
+ GtkWidget *label;
+ GtkWidget *group;
+ PangoAttrList *attrs;
+ int i;
+
+ group = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (group), 6);
+ gtk_grid_set_column_spacing (GTK_GRID (group), 12);
+
+ label = gtk_label_new (title);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ g_object_set (label, "margin-top", 10, "margin-bottom", 10, NULL);
+ attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+ gtk_label_set_attributes (GTK_LABEL (label), attrs);
+ pango_attr_list_unref (attrs);
+ gtk_grid_attach (GTK_GRID (group), label, 0, -1, 3, 1);
+
+ for (i = 0; i < n_tags; i++)
+ {
+ hb_tag_t tag;
+ GtkWidget *feat;
+ FeatureItem *item;
+ GtkWidget *example;
+ char *name;
+
+ tag = hb_tag_from_string (tags[i], -1);
+
+ name = get_feature_display_name (tag);
+ label = gtk_label_new (name);
+ gtk_label_set_xalign (GTK_LABEL (label), 0);
+ gtk_grid_attach (GTK_GRID (group), label, 0, i, 1, 1);
+ g_free (name);
+
+ feat = gtk_drop_down_new (NULL, NULL);
+ gtk_grid_attach (GTK_GRID (group), feat, 1, i, 1, 1);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), feat);
+
+ g_signal_connect (feat, "notify::selected", G_CALLBACK (font_enum_feature_changed_cb), fontchooser);
+
+ example = gtk_label_new ("");
+ gtk_label_set_selectable (GTK_LABEL (example), TRUE);
+ gtk_widget_set_halign (example, GTK_ALIGN_START);
+
+ gtk_grid_attach (GTK_GRID (group), example, 2, i, 1, 1);
+
+ item = g_new (FeatureItem, 1);
+ item->name = tags[i];
+ item->tag = tag;
+ item->top = NULL;
+ item->feat = feat;
+ item->example = example;
+
+ fontchooser->feature_items = g_list_prepend (fontchooser->feature_items, item);
+ }
+
+ gtk_box_append (GTK_BOX (fontchooser->feature_box), group);
+}
+
+static void
+add_radio_group (GtkFontChooserWidget *fontchooser,
+ const char *title,
+ const char **tags,
+ unsigned int n_tags)
{
GtkWidget *label;
GtkWidget *group;
@@ -2202,7 +2423,7 @@ add_radio_group (GtkFontChooserWidget *fontchooser,
pango_attr_list_unref (attrs);
gtk_box_append (GTK_BOX (group), label);
- for (i = 0; tags[i]; i++)
+ for (i = 0; i < n_tags; i++)
{
hb_tag_t tag;
GtkWidget *feat;
@@ -2249,23 +2470,37 @@ add_radio_group (GtkFontChooserWidget *fontchooser,
static void
gtk_font_chooser_widget_populate_features (GtkFontChooserWidget *fontchooser)
{
- const char *ligatures[] = { "liga", "dlig", "hlig", "clig", NULL };
- const char *letter_case[] = { "smcp", "c2sc", "pcap", "c2pc", "unic", "cpsp", "case", NULL };
- const char *number_case[] = { "xxxx", "lnum", "onum", NULL };
- const char *number_spacing[] = { "xxxx", "pnum", "tnum", NULL };
- const char *number_formatting[] = { "zero", "nalt", "frac", NULL };
- const char *char_variants[] = {
+ const char *ligatures[] = { "liga", "dlig", "hlig", "clig" };
+ const char *letter_case[] = { "smcp", "c2sc", "pcap", "c2pc", "unic", "cpsp", "case" };
+ const char *number_case[] = { "xxxx", "lnum", "onum" };
+ const char *number_spacing[] = { "xxxx", "pnum", "tnum" };
+ const char *fractions[] = { "xxxx", "frac", "afrc" };
+ const char *style_variants[] = {
+ "zero", "nalt",
"swsh", "cswh", "calt", "falt", "hist", "salt", "jalt", "titl", "rand",
"ss01", "ss02", "ss03", "ss04", "ss05", "ss06", "ss07", "ss08", "ss09", "ss10",
"ss11", "ss12", "ss13", "ss14", "ss15", "ss16", "ss17", "ss18", "ss19", "ss20",
- NULL };
-
- add_check_group (fontchooser, _("Ligatures"), ligatures);
- add_check_group (fontchooser, _("Letter Case"), letter_case);
- add_radio_group (fontchooser, _("Number Case"), number_case);
- add_radio_group (fontchooser, _("Number Spacing"), number_spacing);
- add_check_group (fontchooser, _("Number Formatting"), number_formatting);
- add_check_group (fontchooser, _("Character Variants"), char_variants);
+ };
+ const char *char_variants[] = {
+ "cv01", "cv02", "cv03", "cv04", "cv05", "cv06", "cv07", "cv08", "cv09", "cv10",
+ "cv11", "cv12", "cv13", "cv14", "cv15", "cv16", "cv17", "cv18", "cv19", "cv20",
+ "cv21", "cv22", "cv23", "cv24", "cv25", "cv26", "cv27", "cv28", "cv29", "cv30",
+ "cv31", "cv32", "cv33", "cv34", "cv35", "cv36", "cv37", "cv38", "cv39", "cv40",
+ "cv41", "cv42", "cv43", "cv44", "cv45", "cv46", "cv47", "cv48", "cv49", "cv50",
+ "cv51", "cv52", "cv53", "cv54", "cv55", "cv56", "cv57", "cv58", "cv59", "cv60",
+ "cv61", "cv62", "cv63", "cv64", "cv65", "cv66", "cv67", "cv68", "cv69", "cv70",
+ "cv71", "cv72", "cv73", "cv74", "cv75", "cv76", "cv77", "cv78", "cv79", "cv80",
+ "cv81", "cv82", "cv83", "cv84", "cv85", "cv86", "cv87", "cv88", "cv89", "cv90",
+ "cv91", "cv92", "cv93", "cv94", "cv95", "cv96", "cv97", "cv98", "cv99",
+ };
+
+ add_check_group (fontchooser, _("Ligatures"), ligatures, G_N_ELEMENTS (ligatures));
+ add_check_group (fontchooser, _("Letter Case"), letter_case, G_N_ELEMENTS (letter_case));
+ add_radio_group (fontchooser, _("Number Case"), number_case, G_N_ELEMENTS (number_case));
+ add_radio_group (fontchooser, _("Number Spacing"), number_spacing, G_N_ELEMENTS (number_spacing));
+ add_radio_group (fontchooser, _("Fractions"), fractions, G_N_ELEMENTS (fractions));
+ add_check_group (fontchooser, _("Style Variations"), style_variants, G_N_ELEMENTS (style_variants));
+ add_enum_group (fontchooser, _("Character Variations"), char_variants, G_N_ELEMENTS (char_variants));
update_font_features (fontchooser);
}
@@ -2286,8 +2521,18 @@ gtk_font_chooser_widget_update_font_features (GtkFontChooserWidget *fontchooser)
for (l = fontchooser->feature_items; l; l = l->next)
{
FeatureItem *item = l->data;
- gtk_widget_hide (item->top);
- gtk_widget_hide (gtk_widget_get_parent (item->top));
+ if (item->top)
+ {
+ gtk_widget_hide (item->top);
+ gtk_widget_hide (gtk_widget_get_parent (item->top));
+ }
+ else
+ {
+ gtk_widget_hide (gtk_widget_get_parent (item->feat));
+ gtk_widget_hide (item->feat);
+ gtk_widget_hide (gtk_widget_get_prev_sibling (item->feat));
+ gtk_widget_hide (item->example);
+ }
}
if ((fontchooser->level & GTK_FONT_CHOOSER_LEVEL_FEATURES) == 0)
@@ -2304,13 +2549,14 @@ gtk_font_chooser_widget_update_font_features (GtkFontChooserWidget *fontchooser)
hb_tag_t features[80];
unsigned int count;
unsigned int n_features;
+ hb_tag_t *feat;
hb_face = hb_font_get_face (hb_font);
find_language_and_script (fontchooser, hb_face, &lang_tag, &script_tag);
n_features = 0;
- for (i = 0; i < 2; i++)
+ for (i = 0; i < G_N_ELEMENTS (table); i++)
{
hb_ot_layout_table_find_script (hb_face, table[i], script_tag, &script_index);
@@ -2318,14 +2564,15 @@ gtk_font_chooser_widget_update_font_features (GtkFontChooserWidget *fontchooser)
hb_ot_layout_script_find_language (hb_face, table[i], script_index, lang_tag, &lang_index);
G_GNUC_END_IGNORE_DEPRECATIONS
- count = G_N_ELEMENTS (features);
+ feat = features + n_features;
+ count = G_N_ELEMENTS (features) - n_features;
hb_ot_layout_language_get_feature_tags (hb_face,
table[i],
script_index,
lang_index,
n_features,
&count,
- features);
+ feat);
n_features += count;
}
@@ -2338,8 +2585,18 @@ gtk_font_chooser_widget_update_font_features (GtkFontChooserWidget *fontchooser)
continue;
has_feature = TRUE;
- gtk_widget_show (item->top);
- gtk_widget_show (gtk_widget_get_parent (item->top));
+ if (item->top)
+ {
+ gtk_widget_show (item->top);
+ gtk_widget_show (gtk_widget_get_parent (item->top));
+ }
+ else
+ {
+ gtk_widget_show (gtk_widget_get_parent (item->feat));
+ gtk_widget_show (item->feat);
+ gtk_widget_show (gtk_widget_get_prev_sibling (item->feat));
+ gtk_widget_show (item->example);
+ }
update_feature_label (fontchooser, item, hb_font, script_tag, lang_tag);
update_feature_example (fontchooser, item, hb_font, script_tag, lang_tag, fontchooser->font_desc);
@@ -2411,6 +2668,19 @@ update_font_features (GtkFontChooserWidget *fontchooser)
g_string_append_c (s, ',');
g_string_append (s, buf);
}
+ else if (GTK_IS_DROP_DOWN (item->feat))
+ {
+ guint value;
+
+ value = gtk_drop_down_get_selected (GTK_DROP_DOWN (item->feat));
+ if (value == 0 || value == GTK_INVALID_LIST_POSITION)
+ continue;
+
+ hb_feature_to_string (&(hb_feature_t) { item->tag, value, 0, -1 }, buf, sizeof (buf));
+ if (s->len > 0)
+ g_string_append_c (s, ',');
+ g_string_append (s, buf);
+ }
}
if (g_strcmp0 (fontchooser->font_features, s->str) != 0)