mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-25 21:21:21 +00:00
Merge branch 'font-chooser-feature-work' into 'main'
fontchooser: Handle font features better See merge request GNOME/gtk!4984
This commit is contained in:
commit
137af44f81
@ -59,4 +59,8 @@ void gdk_source_set_static_name_by_id (guint tag,
|
||||
#define g_source_set_static_name(source, name) g_source_set_name ((source), (name))
|
||||
#endif
|
||||
|
||||
#ifndef I_
|
||||
#define I_(string) g_intern_static_string (string)
|
||||
#endif
|
||||
|
||||
#endif /* __GDK__PRIVATE_H__ */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "gdkintl.h"
|
||||
#include "gdkpipeiostreamprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
@ -408,7 +409,7 @@ gdk_clipboard_class_init (GdkClipboardClass *class)
|
||||
* Emitted when the clipboard changes ownership.
|
||||
*/
|
||||
signals[CHANGED] =
|
||||
g_signal_new ("changed",
|
||||
g_signal_new (I_("changed"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkClipboardClass, changed),
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "gdkclipboard.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
/**
|
||||
* GdkContentProvider:
|
||||
@ -197,7 +198,7 @@ gdk_content_provider_class_init (GdkContentProviderClass *class)
|
||||
* Emitted whenever the content provided by this provider has changed.
|
||||
*/
|
||||
signals[CONTENT_CHANGED] =
|
||||
g_signal_new ("content-changed",
|
||||
g_signal_new (I_("content-changed"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkContentProviderClass, content_changed),
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "gdkpaintable.h"
|
||||
|
||||
#include "gdksnapshotprivate.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
|
||||
void gtk_snapshot_push_debug (GdkSnapshot *snapshot,
|
||||
@ -170,7 +171,7 @@ gdk_paintable_default_init (GdkPaintableInterface *iface)
|
||||
* the icon theme for an icon changing.
|
||||
*/
|
||||
signals[INVALIDATE_CONTENTS] =
|
||||
g_signal_new ("invalidate-contents",
|
||||
g_signal_new (I_("invalidate-contents"),
|
||||
GDK_TYPE_PAINTABLE,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
@ -194,7 +195,7 @@ gdk_paintable_default_init (GdkPaintableInterface *iface)
|
||||
* the contents of a toplevel surface being resized.
|
||||
*/
|
||||
signals[INVALIDATE_SIZE] =
|
||||
g_signal_new ("invalidate-size",
|
||||
g_signal_new (I_("invalidate-size"),
|
||||
GDK_TYPE_PAINTABLE,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <graphene-gobject.h>
|
||||
#include <math.h>
|
||||
@ -247,7 +248,7 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface)
|
||||
* will result in an arbitrary size being used as a result.
|
||||
*/
|
||||
signals[COMPUTE_SIZE] =
|
||||
g_signal_new ("compute-size",
|
||||
g_signal_new (I_("compute-size"),
|
||||
GDK_TYPE_TOPLEVEL,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
|
@ -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_codepoint_t *ch;
|
||||
|
||||
hb_tag_to_string (feature_tag, buf);
|
||||
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);
|
||||
|
||||
glyphs_input = hb_set_create ();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
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_ot_layout_lookup_collect_glyphs (hb_face,
|
||||
HB_OT_TAG_GSUB,
|
||||
lookup_indexes[i],
|
||||
glyphs_before,
|
||||
glyphs_input,
|
||||
glyphs_after,
|
||||
glyphs_output);
|
||||
}
|
||||
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, };
|
||||
|
||||
if (!fontchooser->glyphmap)
|
||||
{
|
||||
fontchooser->glyphmap = hb_map_create ();
|
||||
for (hb_codepoint_t ch = 0; ch < 0xffff; ch++)
|
||||
hb_tag_to_string (feature_tag, buf);
|
||||
|
||||
glyphs_input = hb_set_create ();
|
||||
|
||||
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)
|
||||
{
|
||||
g_string_append_unichar (chars, (gunichar)ch);
|
||||
n_chars++;
|
||||
}
|
||||
}
|
||||
|
||||
hb_set_destroy (glyphs_input);
|
||||
gid = HB_SET_VALUE_INVALID;
|
||||
while (hb_set_next (glyphs_input, &gid))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
g_free (label);
|
||||
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];
|
||||
|
||||
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 };
|
||||
};
|
||||
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);
|
||||
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);
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user