Merge branch 'hint-font-metrics-redux' into 'main'

Add a new font rendering setting

See merge request GNOME/gtk!7113
This commit is contained in:
Matthias Clasen 2024-04-19 17:34:57 +00:00
commit 3fac42fd3c
7 changed files with 149 additions and 237 deletions

View File

@ -1811,6 +1811,7 @@ static TranslationEntry translations[] = {
{ FALSE, "org.gnome.desktop.interface", "font-hinting", "gtk-xft-hinting", G_TYPE_NONE, { .i = 1 } },
{ FALSE, "org.gnome.desktop.interface", "font-hinting", "gtk-xft-hintstyle", G_TYPE_NONE, { .i = 1 } },
{ FALSE, "org.gnome.desktop.interface", "font-rgba-order", "gtk-xft-rgba", G_TYPE_NONE, { .i = 0 } },
{ FALSE, "org.gnome.desktop.interface", "font-rendering", "gtk-font-rendering", G_TYPE_ENUM, { .i = 0 } },
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "antialiasing", "gtk-xft-antialias", G_TYPE_NONE, { .i = 1 } },
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hinting", G_TYPE_NONE, { .i = 1 } },
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hintstyle", G_TYPE_NONE, { .i = 1 } },
@ -2201,6 +2202,11 @@ set_value_from_entry (GdkDisplay *display,
? g_settings_get_boolean (settings, entry->key)
: entry->fallback.b);
break;
case G_TYPE_ENUM:
g_value_set_enum (value, settings && entry->valid
? g_settings_get_enum (settings, entry->key)
: entry->fallback.i);
break;
case G_TYPE_NONE:
if (g_str_equal (entry->setting, "gtk-fontconfig-timestamp"))
g_value_set_uint (value, (guint)entry->fallback.i);

View File

@ -1852,4 +1852,29 @@ typedef enum { /*< prefix=GTK_POPOVER_MENU >*/
GTK_POPOVER_MENU_NESTED = 1 << 0
} GtkPopoverMenuFlags;
/**
* GtkFontRendering:
* @GTK_FONT_RENDERING_AUTOMATIC: Set up font rendering automatically,
* taking factors like screen resolution and scale into account
* @GTK_FONT_RENDERING_MANUAL: Follow low-level font-related settings
* when configuring font rendering
*
* Values for the [property@Gtk.Settings:gtk-font-rendering] setting
* that influence how GTK renders fonts.
*
* The @GTK_FONT_RENDERING_AUTOMATIC value allows GTK to disregard the
* low-level font-related settings:
* [property@Gtk.Settings:gtk-hint-font-metrics],
* [property@Gtk.Settings:gtk-xft-antialias],
* [property@Gtk.Settings:gtk-xft-hinting],
* [property@Gtk.Settings:gtk-xft-hintstyle] and
* [property@Gtk.Settings:gtk-xft-rgba].
*
* Since: 4.16
*/
typedef enum {
GTK_FONT_RENDERING_AUTOMATIC,
GTK_FONT_RENDERING_MANUAL,
} GtkFontRendering;
G_END_DECLS

View File

@ -202,6 +202,7 @@ enum {
PROP_LONG_PRESS_TIME,
PROP_KEYNAV_USE_CARET,
PROP_OVERLAY_SCROLLING,
PROP_FONT_RENDERING,
NUM_PROPERTIES
};
@ -507,7 +508,7 @@ gtk_settings_class_init (GtkSettingsClass *class)
* Since: 4.6
*/
pspecs[PROP_HINT_FONT_METRICS] = g_param_spec_boolean ("gtk-hint-font-metrics", NULL, NULL,
FALSE,
TRUE,
GTK_PARAM_READWRITE);
/**
@ -955,6 +956,18 @@ gtk_settings_class_init (GtkSettingsClass *class)
TRUE,
GTK_PARAM_READWRITE);
/**
* GtkSettings:gtk-font-rendering:
*
* How GTK font rendering is set up.
*
* Since: 4.16
*/
pspecs[PROP_FONT_RENDERING] = g_param_spec_enum ("gtk-font-rendering", NULL, NULL,
GTK_TYPE_FONT_RENDERING,
GTK_FONT_RENDERING_AUTOMATIC,
GTK_PARAM_READWRITE);
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, pspecs);
}
@ -1260,6 +1273,9 @@ gtk_settings_notify (GObject *object,
if (settings_update_fontconfig (settings))
gtk_system_setting_changed (settings->display, GTK_SYSTEM_SETTING_FONT_CONFIG);
break;
case PROP_FONT_RENDERING:
gtk_system_setting_changed (settings->display, GTK_SYSTEM_SETTING_FONT_CONFIG);
break;
case PROP_ENABLE_ANIMATIONS:
settings_invalidate_style (settings);
break;
@ -1773,7 +1789,6 @@ settings_update_xsetting (GtkSettings *settings,
gboolean force)
{
GType value_type;
GType fundamental_type;
gboolean retval = FALSE;
if (settings->property_values[pspec->param_id - 1].source == GTK_SETTINGS_SOURCE_APPLICATION)
@ -1783,10 +1798,8 @@ settings_update_xsetting (GtkSettings *settings,
return FALSE;
value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
fundamental_type = G_TYPE_FUNDAMENTAL (value_type);
if ((g_value_type_transformable (G_TYPE_INT, value_type) &&
!(fundamental_type == G_TYPE_ENUM || fundamental_type == G_TYPE_FLAGS)) ||
if (g_value_type_transformable (G_TYPE_INT, value_type) ||
g_value_type_transformable (G_TYPE_STRING, value_type) ||
g_value_type_transformable (GDK_TYPE_RGBA, value_type))
{

View File

@ -74,6 +74,7 @@
#include "gdk/gdkeventsprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include "gdk/gdkmonitorprivate.h"
#include "gsk/gskdebugprivate.h"
#include "gsk/gskrendererprivate.h"
@ -6463,10 +6464,8 @@ gtk_widget_update_pango_context (GtkWidget *widget,
GtkCssStyle *style = gtk_css_node_get_style (priv->cssnode);
PangoFontDescription *font_desc;
GtkSettings *settings;
cairo_font_options_t *font_options;
guint old_serial;
gboolean hint_font_metrics = FALSE;
int scale;
GtkFontRendering font_rendering;
old_serial = pango_context_get_serial (context);
@ -6474,20 +6473,6 @@ gtk_widget_update_pango_context (GtkWidget *widget,
pango_context_set_font_description (context, font_desc);
pango_font_description_free (font_desc);
scale = gtk_widget_get_scale_factor (widget);
settings = gtk_widget_get_settings (widget);
if (settings)
{
g_object_get (settings, "gtk-hint-font-metrics", &hint_font_metrics, NULL);
/* Override the user setting on non-HiDPI */
if (scale == 1)
hint_font_metrics = TRUE;
pango_context_set_round_glyph_positions (context, hint_font_metrics);
}
if (direction != GTK_TEXT_DIR_NONE)
pango_context_set_base_dir (context, direction == GTK_TEXT_DIR_LTR
? PANGO_DIRECTION_LTR
@ -6495,36 +6480,77 @@ gtk_widget_update_pango_context (GtkWidget *widget,
pango_cairo_context_set_resolution (context, _gtk_css_number_value_get (style->core->dpi, 100));
font_options = (cairo_font_options_t*)g_object_get_qdata (G_OBJECT (widget), quark_font_options);
if (settings && font_options)
{
cairo_font_options_t *options;
options = cairo_font_options_copy (gtk_settings_get_font_options (settings));
cairo_font_options_merge (options, font_options);
cairo_font_options_set_hint_metrics (options,
hint_font_metrics == 1 ? CAIRO_HINT_METRICS_ON
: CAIRO_HINT_METRICS_OFF);
pango_cairo_context_set_font_options (context, options);
cairo_font_options_destroy (options);
}
else if (settings)
{
cairo_font_options_t *options;
options = cairo_font_options_copy (gtk_settings_get_font_options (settings));
cairo_font_options_set_hint_metrics (options,
hint_font_metrics == 1 ? CAIRO_HINT_METRICS_ON
: CAIRO_HINT_METRICS_OFF);
pango_cairo_context_set_font_options (context, options);
cairo_font_options_destroy (options);
}
pango_context_set_font_map (context, gtk_widget_get_effective_font_map (widget));
settings = gtk_widget_get_settings (widget);
if (settings)
g_object_get (settings, "gtk-font-rendering", &font_rendering, NULL);
else
font_rendering = GTK_FONT_RENDERING_AUTOMATIC;
if (font_rendering == GTK_FONT_RENDERING_MANUAL)
{
gboolean hint_font_metrics;
cairo_font_options_t *font_options, *options;
g_object_get (settings, "gtk-hint-font-metrics", &hint_font_metrics, NULL);
options = cairo_font_options_copy (gtk_settings_get_font_options (settings));
font_options = (cairo_font_options_t*)g_object_get_qdata (G_OBJECT (widget), quark_font_options);
if (font_options)
cairo_font_options_merge (options, font_options);
cairo_font_options_set_hint_metrics (options,
hint_font_metrics == 1 ? CAIRO_HINT_METRICS_ON
: CAIRO_HINT_METRICS_OFF);
pango_context_set_round_glyph_positions (context, hint_font_metrics);
pango_cairo_context_set_font_options (context, options);
cairo_font_options_destroy (options);
}
else
{
cairo_font_options_t *options;
double dpi = 96.;
GdkSurface *surface;
surface = gtk_widget_get_surface (widget);
if (surface)
{
GdkDisplay *display;
GdkMonitor *monitor;
display = gdk_surface_get_display (surface);
monitor = gdk_display_get_monitor_at_surface (display, surface);
if (monitor)
dpi = gdk_monitor_get_dpi (monitor);
}
options = cairo_font_options_create ();
cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
if (dpi < 200.)
{
/* Not high-dpi. Prefer sharpness by enabling hinting */
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_SLIGHT);
}
else
{
/* High-dpi. Prefer precise positioning */
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
}
pango_context_set_round_glyph_positions (context, FALSE);
pango_cairo_context_set_font_options (context, options);
cairo_font_options_destroy (options);
}
return old_serial != pango_context_get_serial (context);
}

View File

@ -81,9 +81,7 @@ struct _GtkInspectorVisual
GtkWidget *cursor_size_spin;
GtkWidget *direction_combo;
GtkWidget *font_button;
GtkWidget *font_aa_switch;
GtkWidget *font_hinting_combo;
GtkWidget *metrics_hinting_switch;
GtkWidget *font_rendering_combo;
GtkWidget *animation_switch;
GtkWidget *font_scale_entry;
GtkAdjustment *font_scale_adjustment;
@ -237,108 +235,24 @@ font_scale_adjustment_changed (GtkAdjustment *adjustment,
update_font_scale (vis, factor, FALSE, TRUE, TRUE);
}
static gboolean
get_font_aa (GtkInspectorVisual *vis)
static GtkFontRendering
get_font_rendering (GtkInspectorVisual *vis)
{
int aa;
GtkFontRendering font_rendering;
g_object_get (vis->settings, "gtk-xft-antialias", &aa, NULL);
g_object_get (vis->settings, "gtk-font-rendering", &font_rendering, NULL);
return aa != 0;
}
static gboolean
get_metrics_hinting (GtkInspectorVisual *vis)
{
gboolean hinting;
g_object_get (vis->settings, "gtk-hint-font-metrics", &hinting, NULL);
return hinting;
}
static unsigned int
get_font_hinting (GtkInspectorVisual *vis)
{
int hinting;
char *hint_style_str;
unsigned int hint_style;
g_object_get (vis->settings,
"gtk-xft-hinting", &hinting,
"gtk-xft-hintstyle", &hint_style_str,
NULL);
hint_style = 1;
if (hinting == 0)
{
hint_style = 0;
}
else
{
if (strcmp (hint_style_str, "hintnone") == 0)
hint_style = 0;
else if (strcmp (hint_style_str, "hintslight") == 0)
hint_style = 1;
else if (strcmp (hint_style_str, "hintmedium") == 0)
hint_style = 2;
else if (strcmp (hint_style_str, "hintfull") == 0)
hint_style = 3;
}
g_free (hint_style_str);
return hint_style;
return font_rendering;
}
static void
update_font_hinting (GtkInspectorVisual *vis,
unsigned int hint_style)
update_font_rendering (GtkInspectorVisual *vis,
GtkFontRendering font_rendering)
{
const char *styles[] = { "hintnone", "hintslight", "hintmedium", "hintfull" };
int hinting;
const char *style;
if (get_font_rendering (vis) == font_rendering)
return;
g_object_get (vis->settings,
"gtk-xft-hinting", &hinting,
"gtk-xft-hintstyle", &style,
NULL);
if (hinting != (hint_style != 0) || strcmp (style, styles[hint_style]) != 0)
g_object_set (vis->settings,
"gtk-xft-hinting", hint_style != 0,
"gtk-xft-hintstyle", styles[hint_style],
NULL);
}
static void
font_aa_activate (GtkSwitch *sw,
GParamSpec *pspec,
GtkInspectorVisual *vis)
{
int val, new_val;
g_object_get (vis->settings, "gtk-xft-antialias", &val, NULL);
new_val = gtk_switch_get_active (sw) ? 1 : 0;
if (val != new_val)
g_object_set (vis->settings, "gtk-xft-antialias", new_val, NULL);
}
static void
metrics_hinting_activate (GtkSwitch *sw,
GParamSpec *pspec,
GtkInspectorVisual *vis)
{
gboolean val, new_val;
g_object_get (vis->settings, "gtk-hint-font-metrics", &val, NULL);
new_val = gtk_switch_get_active (sw);
if (val != new_val)
g_object_set (vis->settings, "gtk-hint-font-metrics", new_val, NULL);
g_object_set (vis->settings, "gtk-font-rendering", font_rendering, NULL);
}
static void
@ -1026,29 +940,17 @@ init_font_scale (GtkInspectorVisual *vis)
}
static void
init_font_aa (GtkInspectorVisual *vis)
font_rendering_changed (GtkDropDown *combo,
GParamSpec *pspec,
GtkInspectorVisual *vis)
{
gtk_switch_set_active (GTK_SWITCH (vis->font_aa_switch), get_font_aa (vis));
update_font_rendering (vis, gtk_drop_down_get_selected (combo));
}
static void
font_hinting_changed (GtkDropDown *combo,
GParamSpec *pspec,
GtkInspectorVisual *vis)
init_font_rendering (GtkInspectorVisual *vis)
{
update_font_hinting (vis, gtk_drop_down_get_selected (combo));
}
static void
init_font_hinting (GtkInspectorVisual *vis)
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (vis->font_hinting_combo), get_font_hinting (vis));
}
static void
init_metrics_hinting (GtkInspectorVisual *vis)
{
gtk_switch_set_active (GTK_SWITCH (vis->metrics_hinting_switch), get_metrics_hinting (vis));
gtk_drop_down_set_selected (GTK_DROP_DOWN (vis->font_rendering_combo), get_font_rendering (vis));
}
static void
@ -1299,9 +1201,7 @@ gtk_inspector_visual_class_init (GtkInspectorVisualClass *klass)
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, slowdown_adjustment);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, slowdown_entry);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, visual_box);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, font_aa_switch);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, font_hinting_combo);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, metrics_hinting_switch);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, font_rendering_combo);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, debug_box);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, font_button);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorVisual, font_scale_entry);
@ -1319,9 +1219,7 @@ gtk_inspector_visual_class_init (GtkInspectorVisualClass *klass)
gtk_widget_class_bind_template_callback (widget_class, updates_activate);
gtk_widget_class_bind_template_callback (widget_class, cairo_activate);
gtk_widget_class_bind_template_callback (widget_class, direction_changed);
gtk_widget_class_bind_template_callback (widget_class, font_aa_activate);
gtk_widget_class_bind_template_callback (widget_class, font_hinting_changed);
gtk_widget_class_bind_template_callback (widget_class, metrics_hinting_activate);
gtk_widget_class_bind_template_callback (widget_class, font_rendering_changed);
gtk_widget_class_bind_template_callback (widget_class, baselines_activate);
gtk_widget_class_bind_template_callback (widget_class, layout_activate);
gtk_widget_class_bind_template_callback (widget_class, focus_activate);
@ -1347,9 +1245,7 @@ gtk_inspector_visual_set_display (GtkInspectorVisual *vis,
init_cursor_size (vis);
init_font (vis);
init_font_scale (vis);
init_font_aa (vis);
init_font_hinting (vis);
init_metrics_hinting (vis);
init_font_rendering (vis);
init_animation (vis);
init_slowdown (vis);
init_gl (vis);

View File

@ -358,51 +358,24 @@
<object class="GtkBox">
<property name="spacing">40</property>
<child>
<object class="GtkLabel" id="font_aa_label">
<property name="label" translatable="yes">Antialiasing</property>
<object class="GtkLabel" id="font_rendering_label">
<property name="label" translatable="yes">Rendering</property>
<property name="halign">start</property>
<property name="valign">baseline</property>
<property name="xalign">0.0</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="font_aa_switch">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
<signal name="notify::active" handler="font_aa_activate"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<child>
<object class="GtkBox">
<property name="spacing">40</property>
<child>
<object class="GtkLabel" id="font_hinting_label">
<property name="label" translatable="yes">Hinting</property>
<property name="halign">start</property>
<property name="valign">baseline</property>
<property name="xalign">0.0</property>
</object>
</child>
<child>
<object class="GtkDropDown" id="font_hinting_combo">
<object class="GtkDropDown" id="font_rendering_combo">
<property name="halign">end</property>
<property name="valign">baseline-center</property>
<property name="hexpand">1</property>
<signal name="notify::selected" handler="font_hinting_changed"/>
<signal name="notify::selected" handler="font_rendering_changed"/>
<property name="model">
<object class="GtkStringList">
<items>
<item translatable="yes" context="Font hinting style">None</item>
<item translatable="yes" context="Font hinting style">Slight</item>
<item translatable="yes" context="Font hinting style">Medium</item>
<item translatable="yes" context="Font hinting style">Full</item>
<item translatable="yes" context="Font rendering">Automatic</item>
<item translatable="yes" context="Font rendering">Manual</item>
</items>
</object>
</property>
@ -412,31 +385,6 @@
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<child>
<object class="GtkBox">
<property name="spacing">40</property>
<child>
<object class="GtkLabel" id="metrics_hinting_label">
<property name="label" translatable="yes">Metrics Hinting</property>
<property name="halign">start</property>
<property name="valign">baseline</property>
<property name="xalign">0.0</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="metrics_hinting_switch">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
<signal name="notify::active" handler="metrics_hinting_activate"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
@ -787,9 +735,7 @@
<widget name="cursor_label"/>
<widget name="cursor_size_label"/>
<widget name="font_label"/>
<widget name="font_aa_label"/>
<widget name="font_hinting_label"/>
<widget name="metrics_hinting_label"/>
<widget name="font_rendering_label"/>
<widget name="direction_label"/>
<widget name="animation_label"/>
<widget name="updates_label"/>
@ -813,7 +759,7 @@
<widget name="cursor_combo"/>
<widget name="font_button"/>
<widget name="direction_combo"/>
<widget name="font_hinting_combo"/>
<widget name="font_rendering_combo"/>
</widgets>
</object>
<object class="GtkSizeGroup">

View File

@ -10,7 +10,7 @@ echo "1..1"
name=gtk-query-settings
result=$TEST_RESULT_DIR/$name.out
$GTK_QUERY_SETTINGS 2>/dev/null >$result
EXPECTED=51
EXPECTED=52
SEEN=$(wc -l $result | cut -f1 -d' ')
if [ $SEEN -eq $EXPECTED ]; then