diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-08-25 22:26:07 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-08-26 17:53:55 -0400 |
commit | 0441fd367866c8ab7aa3d7646adddbcf93ac50e6 (patch) | |
tree | 0693ae7d5aebb92a57f9c339355f116f61b9e0d5 | |
parent | 2017f3debee788b993363b1ed0fcce8629f2560c (diff) | |
download | gtk+-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.c | 468 |
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) |