Commit 8f3399d4 authored by Owen Taylor's avatar Owen Taylor Committed by Owen Taylor

Change machinery for following font rendering xsettings to set cairo font

2005-07-19  Owen Taylor  <otaylor@redhat.com>

        * gtk/gtksettings.c gtk/gtkwidget.c: Change machinery for
        following font rendering xsettings to set cairo font
        options on PangoContext

        * gdk/x11/gdkxftdefaults.c gdk/x11/gdkevents-x11.c gdkscreen-x11.h
        gdkprivate-x11.h: Get default values for rendering options
        (such as antialiasing, dpi) from the Xft resources for the
        display, borrowing a bit of code from Xft.

        * gtk/gtksettings.c (gtk_settings_class_init): Fix docs for
        values of gtk-xft-hintstyle.
parent 68bcd510
2005-07-19 Owen Taylor <otaylor@redhat.com>
* gtk/gtksettings.c gtk/gtkwidget.c: Change machinery for
following font rendering xsettings to set cairo font
options on PangoContext
* gdk/x11/gdkxftdefaults.c gdk/x11/gdkevents-x11.c gdkscreen-x11.h
gdkprivate-x11.h: Get default values for rendering options
(such as antialiasing, dpi) from the Xft resources for the
display, borrowing a bit of code from Xft.
* gtk/gtksettings.c (gtk_settings_class_init): Fix docs for
values of gtk-xft-hintstyle.
2005-07-21 Tor Lillqvist <tml@novell.com>
* gtk/gtk.symbols: Make GtkPlug/Socket API available with all
......
2005-07-19 Owen Taylor <otaylor@redhat.com>
* gtk/gtksettings.c gtk/gtkwidget.c: Change machinery for
following font rendering xsettings to set cairo font
options on PangoContext
* gdk/x11/gdkxftdefaults.c gdk/x11/gdkevents-x11.c gdkscreen-x11.h
gdkprivate-x11.h: Get default values for rendering options
(such as antialiasing, dpi) from the Xft resources for the
display, borrowing a bit of code from Xft.
* gtk/gtksettings.c (gtk_settings_class_init): Fix docs for
values of gtk-xft-hintstyle.
2005-07-21 Tor Lillqvist <tml@novell.com>
* gtk/gtk.symbols: Make GtkPlug/Socket API available with all
......
2005-07-19 Owen Taylor <otaylor@redhat.com>
* gtk/gtksettings.c gtk/gtkwidget.c: Change machinery for
following font rendering xsettings to set cairo font
options on PangoContext
* gdk/x11/gdkxftdefaults.c gdk/x11/gdkevents-x11.c gdkscreen-x11.h
gdkprivate-x11.h: Get default values for rendering options
(such as antialiasing, dpi) from the Xft resources for the
display, borrowing a bit of code from Xft.
* gtk/gtksettings.c (gtk_settings_class_init): Fix docs for
values of gtk-xft-hintstyle.
2005-07-21 Tor Lillqvist <tml@novell.com>
* gtk/gtk.symbols: Make GtkPlug/Socket API available with all
......
......@@ -49,6 +49,7 @@ libgdk_x11_la_SOURCES = \
gdkvisual-x11.c \
gdkwindow-x11.c \
gdkwindow-x11.h \
gdkxftdefaults.c \
gdkxid.c \
gdkx.h \
gdkprivate-x11.h \
......
......@@ -2895,7 +2895,7 @@ gdk_screen_get_setting (GdkScreen *screen,
const char *xsettings_name = NULL;
XSettingsResult result;
XSettingsSetting *setting;
XSettingsSetting *setting = NULL;
GdkScreenX11 *screen_x11;
gboolean success = FALSE;
gint i;
......@@ -2913,12 +2913,12 @@ gdk_screen_get_setting (GdkScreen *screen,
}
if (!xsettings_name)
return FALSE;
goto out;
result = xsettings_client_get_setting (screen_x11->xsettings_client,
xsettings_name, &setting);
if (result != XSETTINGS_SUCCESS)
return FALSE;
goto out;
switch (setting->type)
{
......@@ -2965,9 +2965,14 @@ gdk_screen_get_setting (GdkScreen *screen,
g_value_unset (&tmp_val);
xsettings_setting_free (setting);
out:
if (setting)
xsettings_setting_free (setting);
return success;
if (success)
return TRUE;
else
return _gdk_x11_get_xft_setting (screen, name, value);
}
static GdkFilterReturn
......
......@@ -176,6 +176,10 @@ PangoRenderer *_gdk_x11_renderer_get (GdkDrawable *drawable,
void _gdk_x11_cursor_update_theme (GdkCursor *cursor);
gboolean _gdk_x11_get_xft_setting (GdkScreen *screen,
const gchar *name,
GValue *value);
extern GdkDrawableClass _gdk_x11_drawable_class;
extern gboolean _gdk_use_xshm;
extern const int _gdk_nenvent_masks;
......
......@@ -93,6 +93,16 @@ struct _GdkScreenX11
/* Pango renderer object singleton */
PangoRenderer *renderer;
/* Xft resources for the display, used for default values for
* the Xft/ XSETTINGS
*/
gboolean xft_init; /* Whether we've intialized these values yet */
gboolean xft_antialias;
gboolean xft_hinting;
gint xft_hintstyle;
gint xft_rgba;
gint xft_dpi;
};
struct _GdkScreenX11Class
......
/* GDK - The GIMP Drawing Kit
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Based on code from xftdpy.c
*
* Copyright © 2000 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <fontconfig/fontconfig.h>
#include <gdkscreen-x11.h>
#include <gdkx.h>
static gint
parse_boolean (char *v)
{
gchar c0, c1;
c0 = *v;
if (g_ascii_isupper ((int)c0))
c0 = g_ascii_tolower (c0);
if (c0 == 't' || c0 == 'y' || c0 == '1')
return 1;
if (c0 == 'f' || c0 == 'n' || c0 == '0')
return 0;
if (c0 == 'o')
{
c1 = v[1];
if (g_ascii_isupper ((int)c1))
c1 = g_ascii_tolower (c1);
if (c1 == 'n')
return 1;
if (c1 == 'f')
return 0;
}
return -1;
}
static gboolean
get_boolean_default (Display *dpy,
gchar *option,
gboolean *value)
{
gchar *v;
gint i;
v = XGetDefault (dpy, "Xft", option);
if (v)
{
i = parse_boolean (v);
if (i >= 0)
{
*value = i;
return TRUE;
}
}
return FALSE;
}
static gboolean
get_double_default (Display *dpy,
gchar *option,
gdouble *value)
{
gchar *v, *e;
v = XGetDefault (dpy, "Xft", option);
if (v)
{
/* Xft uses strtod, though localization probably wasn't
* desired. For compatibility, we use the conservative
* g_strtod() that accepts either localized or non-localized
* decimal separator.
*/
*value = g_strtod (v, &e);
if (e != v)
return TRUE;
}
return FALSE;
}
static gboolean
get_integer_default (Display *dpy,
gchar *option,
gint *value)
{
gint i;
gchar *v, *e;
v = XGetDefault (dpy, "Xft", option);
if (v)
{
if (FcNameConstant ((FcChar8 *) v, value))
return TRUE;
i = strtol (v, &e, 0);
if (e != v)
return TRUE;
}
return FALSE;
}
static void
init_xft_settings (GdkScreen *screen)
{
GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
int xscreen = GDK_SCREEN_XNUMBER (screen);
double dpi_double;
if (screen_x11->xft_init)
return;
screen_x11->xft_init = TRUE;
if (!get_boolean_default (xdisplay, "antialias", &screen_x11->xft_antialias))
screen_x11->xft_antialias = TRUE;
if (!get_boolean_default (xdisplay, "hinting", &screen_x11->xft_hinting))
screen_x11->xft_hinting = TRUE;
if (!get_integer_default (xdisplay, "hintstyle", &screen_x11->xft_hintstyle))
screen_x11->xft_hintstyle = FC_HINT_FULL;
if (!get_integer_default (xdisplay, "rgba", &screen_x11->xft_rgba))
{
int subpixel = FC_RGBA_UNKNOWN;
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
if (_gdk_x11_have_render (screen_x11->display))
{
int render_order = XRenderQuerySubpixelOrder (xdisplay, xscreen);
switch (render_order)
{
default:
case SubPixelUnknown:
subpixel = FC_RGBA_UNKNOWN;
break;
case SubPixelHorizontalRGB:
subpixel = FC_RGBA_RGB;
break;
case SubPixelHorizontalBGR:
subpixel = FC_RGBA_BGR;
break;
case SubPixelVerticalRGB:
subpixel = FC_RGBA_VRGB;
break;
case SubPixelVerticalBGR:
subpixel = FC_RGBA_VBGR;
break;
case SubPixelNone:
subpixel = FC_RGBA_NONE;
break;
}
}
screen_x11->xft_rgba = subpixel;
#endif
}
if (!get_double_default (xdisplay, "dpi", &dpi_double))
dpi_double = (((double) DisplayHeight (xdisplay, xscreen) * 25.4) /
(double) DisplayHeightMM (xdisplay, xscreen));
screen_x11->xft_dpi = (int)(0.5 + PANGO_SCALE * dpi_double);
}
gboolean
_gdk_x11_get_xft_setting (GdkScreen *screen,
const gchar *name,
GValue *value)
{
GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
if (strncmp (name, "gtk-xft-", 8) != 0)
return FALSE;
name += 8;
init_xft_settings (screen);
if (strcmp (name, "antialias") == 0)
{
g_value_set_int (value, screen_x11->xft_antialias);
return TRUE;
}
else if (strcmp (name, "hinting") == 0)
{
g_value_set_int (value, screen_x11->xft_hinting);
return TRUE;
}
else if (strcmp (name, "hintstyle") == 0)
{
const char *str;
switch (screen_x11->xft_hintstyle)
{
case FC_HINT_NONE:
str = "hintnone";
break;
case FC_HINT_SLIGHT:
str = "hintslight";
break;
case FC_HINT_MEDIUM:
str = "hintmedium";
break;
case FC_HINT_FULL:
str = "hintfull";
break;
default:
return FALSE;
}
g_value_set_string (value, str);
return TRUE;
}
else if (strcmp (name, "rgba") == 0)
{
const char *str;
switch (screen_x11->xft_rgba)
{
case FC_RGBA_NONE:
str = "none";
break;
case FC_RGBA_RGB:
str = "rgb";
break;
case FC_RGBA_BGR:
str = "bgr";
break;
case FC_RGBA_VRGB:
str = "vrgb";
break;
case FC_RGBA_VBGR:
str = "vbgr";
break;
case FC_RGBA_UNKNOWN:
default:
return FALSE;
}
g_value_set_string (value, str);
return TRUE;
}
else if (strcmp (name, "dpi") == 0)
{
g_value_set_int (value, screen_x11->xft_dpi);
return TRUE;
}
return FALSE;
}
......@@ -143,88 +143,6 @@ gtk_settings_get_type (void)
return settings_type;
}
#if 0
static void
gtk_default_substitute (FcPattern *pattern,
gpointer data)
{
GtkSettings *settings = data;
gint antialias;
gint hinting;
char *rgba;
char *hintstyle;
gint dpi;
FcValue v;
g_object_get (settings,
"gtk-xft-antialias", &antialias,
"gtk-xft-hinting", &hinting,
"gtk-xft-hintstyle", &hintstyle,
"gtk-xft-rgba", &rgba,
"gtk-xft-dpi", &dpi,
NULL);
if (antialias >= 0 &&
FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
FcPatternAddBool (pattern, FC_ANTIALIAS, antialias != 0);
if (hinting >= 0 &&
FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
FcPatternAddBool (pattern, FC_HINTING, hinting != 0);
#ifdef FC_HINT_STYLE
if (hintstyle && FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
{
int val = FC_HINT_FULL; /* Quiet GCC */
gboolean found = TRUE;
if (strcmp (hintstyle, "hintnone") == 0)
val = FC_HINT_NONE;
else if (strcmp (hintstyle, "hintslight") == 0)
val = FC_HINT_SLIGHT;
else if (strcmp (hintstyle, "hintmedium") == 0)
val = FC_HINT_MEDIUM;
else if (strcmp (hintstyle, "hintfull") == 0)
val = FC_HINT_FULL;
else
found = FALSE;
if (found)
FcPatternAddInteger (pattern, FC_HINT_STYLE, val);
}
#endif /* FC_HINT_STYLE */
if (rgba && FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
{
int val = FC_RGBA_NONE; /* Quiet GCC */
gboolean found = TRUE;
if (strcmp (rgba, "none") == 0)
val = FC_RGBA_NONE;
else if (strcmp (rgba, "rgb") == 0)
val = FC_RGBA_RGB;
else if (strcmp (rgba, "bgr") == 0)
val = FC_RGBA_BGR;
else if (strcmp (rgba, "vrgb") == 0)
val = FC_RGBA_VRGB;
else if (strcmp (rgba, "vbgr") == 0)
val = FC_RGBA_VBGR;
else
found = FALSE;
if (found)
FcPatternAddInteger (pattern, FC_RGBA, val);
}
if (dpi >= 0 && FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch)
FcPatternAddDouble (pattern, FC_DPI, dpi / 1024.);
g_free (hintstyle);
g_free (rgba);
}
#endif /* GDK_WINDOWING_X11 */
static void
gtk_settings_init (GtkSettings *settings)
{
......@@ -411,7 +329,7 @@ gtk_settings_class_init (GtkSettingsClass *class)
result = settings_install_property_parser (class,
g_param_spec_string ("gtk-xft-hintstyle",
P_("Xft Hint Style"),
P_("What degree of hinting to use; none, slight, medium, or full"),
P_("What degree of hinting to use; hintnone, hintslight, hintmedium, or hintfull"),
NULL,
GTK_PARAM_READWRITE),
NULL);
......@@ -509,15 +427,6 @@ gtk_settings_get_for_screen (GdkScreen *screen)
settings->screen = screen;
g_object_set_data (G_OBJECT (screen), "gtk-settings", settings);
#if 0
/* Set the default substitution function for the Pango fontmap.
*/
pango_xft_set_default_substitute (GDK_SCREEN_XDISPLAY (screen),
GDK_SCREEN_XNUMBER (screen),
gtk_default_substitute,
settings, NULL);
#endif /* GDK_WINDOWING_X11 */
gtk_rc_reparse_all_for_settings (settings, TRUE);
settings_update_double_click (settings);
}
......@@ -646,22 +555,18 @@ gtk_settings_notify (GObject *object,
case PROP_DOUBLE_CLICK_DISTANCE:
settings_update_double_click (settings);
break;
#if 0
#ifdef GDK_WINDOWING_X11
case PROP_XFT_DPI:
case PROP_XFT_ANTIALIAS:
case PROP_XFT_HINTING:
case PROP_XFT_HINTSTYLE:
case PROP_XFT_RGBA:
case PROP_XFT_DPI:
pango_xft_substitute_changed (GDK_SCREEN_XDISPLAY (settings->screen),
GDK_SCREEN_XNUMBER (settings->screen));
/* This is a hack because with gtk_rc_reset_styles() doesn't get
* widgets with gtk_widget_style_set(), and also causes more
* recomputation than necessary.
*/
gtk_rc_reset_styles (GTK_SETTINGS (object));
break;
#endif
#ifdef GDK_WINDOWING_X11
case PROP_CURSOR_THEME_NAME:
case PROP_CURSOR_THEME_SIZE:
settings_update_cursor_theme (settings);
......
......@@ -204,6 +204,7 @@ static gboolean gtk_widget_real_focus_out_event (GtkWidget *widget,
static gboolean gtk_widget_real_focus (GtkWidget *widget,
GtkDirectionType direction);
static PangoContext* gtk_widget_peek_pango_context (GtkWidget *widget);
static void gtk_widget_update_pango_context (GtkWidget *widget);
static void gtk_widget_propagate_state (GtkWidget *widget,
GtkStateData *data);
static void gtk_widget_reset_rc_style (GtkWidget *widget);
......@@ -4932,13 +4933,6 @@ gtk_widget_set_style_internal (GtkWidget *widget,
g_object_ref (widget);
g_object_freeze_notify (G_OBJECT (widget));
if (widget->style != style || initial_emission)
{
PangoContext *context = gtk_widget_peek_pango_context (widget);
if (context)
pango_context_set_font_description (context, style->font_desc);
}
if (widget->style != style)
{
GtkStyle *previous_style;
......@@ -4956,6 +4950,7 @@ gtk_widget_set_style_internal (GtkWidget *widget,
if (GTK_WIDGET_REALIZED (widget))
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_widget_update_pango_context (widget);
g_signal_emit (widget,
widget_signals[STYLE_SET],
0,
......@@ -4966,10 +4961,13 @@ gtk_widget_set_style_internal (GtkWidget *widget,
gtk_widget_queue_resize (widget);
}
else if (initial_emission)
g_signal_emit (widget,
widget_signals[STYLE_SET],
0,
NULL);
{
gtk_widget_update_pango_context (widget);
g_signal_emit (widget,
widget_signals[STYLE_SET],
0,
NULL);
}
g_object_notify (G_OBJECT (widget), "style");
g_object_thaw_notify (G_OBJECT (widget));
g_object_unref (widget);
......@@ -5195,6 +5193,101 @@ gtk_widget_get_pango_context (GtkWidget *widget)
return context;
}
static void
update_pango_context (GtkWidget *widget,
PangoContext *context)
{
#ifdef GDK_WINDOWING_X11
GtkSettings *settings;
gint hinting;
char *hint_style_str;
cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_DEFAULT;
gint antialias;
cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_DEFAULT;
char *rgba_str;
cairo_subpixel_order_t subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
int dpi;
cairo_font_options_t *options;
#endif
pango_context_set_font_description (context, widget->style->font_desc);
pango_context_set_base_dir (context,
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL);
#ifdef GDK_WINDOWING_X11
settings = gtk_widget_get_settings (widget);
g_object_get (settings,
"gtk-xft-antialias", &antialias,
"gtk-xft-hinting", &hinting,
"gtk-xft-hintstyle", &hint_style_str,
"gtk-xft-rgba", &rgba_str,
"gtk-xft-dpi", &dpi,
NULL);
if (dpi > 0)
pango_cairo_context_set_resolution (context, dpi / 1024.);
else
pango_cairo_context_set_resolution (context, -1.);
options = cairo_font_options_create ();
if (hinting >= 0 && !hinting)
{
hint_style = CAIRO_HINT_STYLE_NONE;
}
else if (hint_style_str)
{