diff options
author | Owen Taylor <otaylor@src.gnome.org> | 2002-07-24 02:39:03 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2002-07-24 02:39:03 +0000 |
commit | 05fb268094d119c236f4a01689fc5aa722cf4bac (patch) | |
tree | 5a7af868b7b0b540a44f90674e4281695b5b26ec | |
parent | a8339d6fc10ebc65518b7641cb6327f4cc77b796 (diff) | |
download | gnome-control-center-05fb268094d119c236f4a01689fc5aa722cf4bac.tar.gz |
ue Jul 23 22:35:10 2002 Owen Taylor <otaylor@redhat.com>
* acconfig.h configure.in: Check for Xft2.
* capplets/font/main.c capplets/font/Makefile.am
capplets/font/font-properties.glade: If XFt2 is present,
allow the user to control various font rendering attributes.
* gnome-settings-daemon/gnome-settings-xsettings.c:
Mirror the Xft rendering attributes from the font
capplet to XSETTINGS and Xrdb.
* schemas/Makefile.am schemas/desktop_gnome_font_rendering.schemas:
Add schemas for the new GConf settings.
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | acconfig.h | 3 | ||||
-rw-r--r-- | capplets/font/Makefile.am | 15 | ||||
-rw-r--r-- | capplets/font/font-properties.glade | 1177 | ||||
-rw-r--r-- | capplets/font/main.c | 639 | ||||
-rw-r--r-- | configure.in | 18 | ||||
-rw-r--r-- | gnome-settings-daemon/gnome-settings-xsettings.c | 296 | ||||
-rw-r--r-- | schemas/Makefile.am | 3 | ||||
-rw-r--r-- | schemas/desktop_gnome_font_rendering.schemas | 69 |
9 files changed, 2224 insertions, 11 deletions
@@ -1,3 +1,18 @@ +Tue Jul 23 22:35:10 2002 Owen Taylor <otaylor@redhat.com> + + * acconfig.h configure.in: Check for Xft2. + + * capplets/font/main.c capplets/font/Makefile.am + capplets/font/font-properties.glade: If XFt2 is present, + allow the user to control various font rendering attributes. + + * gnome-settings-daemon/gnome-settings-xsettings.c: + Mirror the Xft rendering attributes from the font + capplet to XSETTINGS and Xrdb. + + * schemas/Makefile.am schemas/desktop_gnome_font_rendering.schemas: + Add schemas for the new GConf settings. + Tue Jul 23 22:06:08 2002 Owen Taylor <otaylor@redhat.com> * capplets/keyboard/gnome-keyboard-properties.c: Fix diff --git a/acconfig.h b/acconfig.h index bd700a284..bee93fe2b 100644 --- a/acconfig.h +++ b/acconfig.h @@ -20,6 +20,9 @@ #undef u_int64_t #undef int64_t +/* Define if the system has Xft version 2 and fontconfig */ +#undef HAVE_XFT2 + #undef HAVE_DEVGTK #undef WITH_SYMBOL_UNDERSCORE diff --git a/capplets/font/Makefile.am b/capplets/font/Makefile.am index ba6ea67d7..43d7b8d89 100644 --- a/capplets/font/Makefile.am +++ b/capplets/font/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS = gnome-font-properties -gnome_font_properties_LDADD = $(GNOMECC_CAPPLETS_LIBS) +gnome_font_properties_LDADD = $(FONT_CAPPLET_LIBS) $(top_builddir)/capplets/common/libcommon.la gnome_font_properties_SOURCES = \ main.c gnome_font_properties_LDFLAGS = -export-dynamic @@ -10,6 +10,13 @@ gnome_font_properties_LDFLAGS = -export-dynamic iconsdir = $(GNOMECC_ICONS_DIR) icons_DATA = font-capplet.png +pixmapdir = $(GNOMECC_PIXMAPS_DIR) +pixmap_DATA = \ + subpixel-rgb.png \ + subpixel-bgr.png \ + subpixel-vrgb.png \ + subpixel-vbgr.png + desktop_iconsdir = $(datadir)/pixmaps desktop_icons_DATA = font-capplet.png @@ -20,7 +27,9 @@ desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop) gladedir = $(GNOMECC_GLADE_DIR) glade_DATA = font-properties.glade -INCLUDES = $(GNOMECC_CAPPLETS_CFLAGS) \ - -DGLADEDIR=\""$(gladedir)"\" +INCLUDES = $(FONT_CAPPLET_CFLAGS) \ + $(GNOMECC_CAPPLETS_CFLAGS) \ + -DGLADEDIR=\""$(gladedir)"\" \ + -DPIXMAPDIR=\""$(pixmapdir)"\" CLEANFILES = $(GNOMECC_CAPPLETS_CLEANFILES) EXTRA_DIST = $(Desktop_in_files) $(icons_DATA) $(glade_DATA) diff --git a/capplets/font/font-properties.glade b/capplets/font/font-properties.glade index 4fe741fa1..b0ff17551 100644 --- a/capplets/font/font-properties.glade +++ b/capplets/font/font-properties.glade @@ -5,14 +5,13 @@ <requires lib="gnome"/> <widget class="GtkDialog" id="font_dialog"> - <property name="visible">True</property> <property name="title" translatable="yes">Font Preferences</property> <property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="window_position">GTK_WIN_POS_NONE</property> <property name="modal">False</property> - <property name="resizable">True</property> + <property name="resizable">False</property> <property name="destroy_with_parent">False</property> - <property name="has_separator">True</property> + <property name="has_separator">False</property> <child internal-child="vbox"> <widget class="GtkVBox" id="dialog-vbox1"> @@ -65,9 +64,8 @@ <child> <widget class="GtkTable" id="table3"> <property name="border_width">5</property> - <property name="width_request">375</property> <property name="visible">True</property> - <property name="n_rows">2</property> + <property name="n_rows">3</property> <property name="n_columns">2</property> <property name="homogeneous">False</property> <property name="row_spacing">8</property> @@ -161,6 +159,1175 @@ <property name="y_options"></property> </packing> </child> + + <child> + <widget class="GtkFrame" id="font_render_frame"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkTable" id="table4"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">5</property> + <property name="column_spacing">5</property> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="monochrome_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Monochrome</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="monochrome_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="best_shapes_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Best _shapes</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">monochrome_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="best_shapes_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="best_contrast_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Best co_ntrast</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">monochrome_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment3"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="best_contrast_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="subpixel_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Sub_pixel smoothing (LCDs)</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">monochrome_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment4"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="subpixel_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment13"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkButton" id="details_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">De_tails...</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + </widget> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="label" translatable="yes">Font Rendering</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="render_details"> + <property name="title" translatable="yes">Font Rendering Details</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">False</property> + <property name="destroy_with_parent">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox3"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area3"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <property name="spacing">10</property> + + <child> + <widget class="GtkButton" id="button1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-help</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-11</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button2"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-7</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox7"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkAlignment" id="alignment5"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">10</property> + + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="label" translatable="yes">Resolution (_dots per inch):</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">dpi_spinner</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="dpi_spinner"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">False</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">96 50 200 1 10 10</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox8"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="label" translatable="yes">Smoothing:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table5"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox12"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="antialias_none_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_None</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment6"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="antialias_none_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox13"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="antialias_grayscale_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">G_rayscale</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">antialias_none_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment7"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="antialias_grayscale_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox14"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="antialias_subpixel_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Sub_pixel (LCDs)</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">antialias_none_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment8"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="antialias_subpixel_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox9"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes">Hinting:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table6"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox15"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="hint_none_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">N_one</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment9"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="hint_none_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox16"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="hint_slight_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Slight</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">hint_none_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment10"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="hint_slight_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox17"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="hint_medium_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Medium</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">hint_none_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment11"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="hint_medium_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox18"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="hint_full_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Full</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">hint_none_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment12"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkDrawingArea" id="hint_full_sample"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox10"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes">Subpixel order:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table7"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">5</property> + <property name="column_spacing">5</property> + + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="subpixel_rgb_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_RGB</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkImage" id="subpixel_rgb_image"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="subpixel_bgr_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_BGR</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">subpixel_rgb_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkImage" id="subpixel_bgr_image"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="subpixel_vrgb_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_VRGB</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">subpixel_rgb_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkImage" id="subpixel_vrgb_image"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="subpixel_vbgr_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">VB_GR</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">subpixel_rgb_radio</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkImage" id="subpixel_vbgr_image"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> </widget> <packing> <property name="padding">0</property> diff --git a/capplets/font/main.c b/capplets/font/main.c index c96faa323..764804fac 100644 --- a/capplets/font/main.c +++ b/capplets/font/main.c @@ -8,15 +8,37 @@ #include <gtk/gtk.h> #include <gconf/gconf-client.h> #include <glade/glade.h> +#include <stdarg.h> + +#ifdef HAVE_XFT2 +#include <gdk/gdkx.h> +#include <X11/Xft/Xft.h> +#endif /* HAVE_XFT2 */ #include "theme-common.h" #include "capplet-util.h" #include "activate-settings-daemon.h" #include "gconf-property-editor.h" + +#ifdef HAVE_XFT2 +static void cb_show_details (GtkWidget *button, + GtkWindow *parent); +#endif /* HAVE_XFT2 */ + #define GTK_FONT_KEY "/desktop/gnome/interface/font_name" #define DESKTOP_FONT_KEY "/apps/nautilus/preferences/desktop_font" +#ifdef HAVE_XFT2 +#define FONT_RENDER_DIR "/desktop/gnome/font_rendering" +#define FONT_ANTIALIASING_KEY FONT_RENDER_DIR "/antialiasing" +#define FONT_HINTING_KEY FONT_RENDER_DIR "/hinting" +#define FONT_RGBA_ORDER_KEY FONT_RENDER_DIR "/rgba_order" +#define FONT_DPI_KEY FONT_RENDER_DIR "/dpi" + +static gboolean in_change = FALSE; +#endif /* HAVE_XFT2 */ + static GladeXML * create_dialog (void) { @@ -38,6 +60,344 @@ cb_dialog_response (GtkDialog *dialog, gint response_id) gtk_main_quit (); } +#ifdef HAVE_XFT2 + +/* + * Code for displaying previews of font rendering with various Xft options + */ + +static void +sample_size_request (GtkWidget *darea, + GtkRequisition *requisition) +{ + GdkPixbuf *pixbuf = g_object_get_data (G_OBJECT (darea), "sample-pixbuf"); + + requisition->width = gdk_pixbuf_get_width (pixbuf) + 2; + requisition->height = gdk_pixbuf_get_height (pixbuf) + 2; +} + +static void +sample_expose (GtkWidget *darea, + GdkEventExpose expose) +{ + GdkPixbuf *pixbuf = g_object_get_data (G_OBJECT (darea), "sample-pixbuf"); + int width = gdk_pixbuf_get_width (pixbuf); + int height = gdk_pixbuf_get_height (pixbuf); + + int x = (darea->allocation.width - width) / 2; + int y = (darea->allocation.height - height) / 2; + + gdk_draw_rectangle (darea->window, darea->style->white_gc, TRUE, + 0, 0, + darea->allocation.width, darea->allocation.height); + gdk_draw_rectangle (darea->window, darea->style->black_gc, FALSE, + 0, 0, + darea->allocation.width - 1, darea->allocation.height - 1); + + gdk_pixbuf_render_to_drawable (pixbuf, darea->window, NULL, + 0, 0, x, y, width, height, + GDK_RGB_DITHER_NORMAL, 0, 0); +} + +typedef enum { + ANTIALIAS_NONE, + ANTIALIAS_GRAYSCALE, + ANTIALIAS_RGBA +} Antialiasing; + +static GConfEnumStringPair antialias_enums[] = { + { ANTIALIAS_NONE, "none" }, + { ANTIALIAS_GRAYSCALE, "grayscale" }, + { ANTIALIAS_RGBA, "rgba" }, + { -1, NULL } +}; + +typedef enum { + HINT_NONE, + HINT_SLIGHT, + HINT_MEDIUM, + HINT_FULL +} Hinting; + +static GConfEnumStringPair hint_enums[] = { + { HINT_NONE, "none" }, + { HINT_SLIGHT, "slight" }, + { HINT_MEDIUM, "medium" }, + { HINT_FULL, "full" }, + { -1, NULL } +}; + +typedef enum { + RGBA_RGB, + RGBA_BGR, + RGBA_VRGB, + RGBA_VBGR +} RgbaOrder; + +static GConfEnumStringPair rgba_order_enums[] = { + { RGBA_RGB, "rgb" }, + { RGBA_BGR, "bgr" }, + { RGBA_VRGB, "vrgb" }, + { RGBA_VBGR, "vbgr" }, + { -1, NULL } +}; + +static XftFont * +open_pattern (FcPattern *pattern, + Antialiasing antialiasing, + Hinting hinting) +{ +#ifdef FC_HINT_STYLE + static const int hintstyles[] = { FC_HINT_NONE, FC_HINT_SLIGHT, FC_HINT_MEDIUM, FC_HINT_FULL }; +#endif /* FC_HINT_STYLE */ + + FcPattern *res_pattern; + FcResult result; + XftFont *font; + + Display *xdisplay = gdk_x11_get_default_xdisplay (); + int screen = gdk_x11_get_default_screen (); + + res_pattern = XftFontMatch (xdisplay, screen, pattern, &result); + + FcPatternDel (res_pattern, FC_HINTING); + FcPatternAddBool (res_pattern, FC_HINTING, hinting != HINT_NONE); + +#ifdef FC_HINT_STYLE + FcPatternDel (res_pattern, FC_HINT_STYLE); + FcPatternAddInteger (res_pattern, FC_HINT_STYLE, hintstyles[hinting]); +#endif /* FC_HINT_STYLE */ + + FcPatternDel (res_pattern, FC_ANTIALIAS); + FcPatternAddBool (res_pattern, FC_ANTIALIAS, antialiasing != ANTIALIAS_NONE); + + FcPatternDel (res_pattern, FC_RGBA); + FcPatternAddInteger (res_pattern, FC_RGBA, + antialiasing == ANTIALIAS_RGBA ? FC_RGBA_RGB : FC_RGBA_NONE); + + FcPatternDel (res_pattern, FC_DPI); + FcPatternAddInteger (res_pattern, FC_DPI, 96); + + font = XftFontOpenPattern (xdisplay, res_pattern); + if (!font) + FcPatternDestroy (res_pattern); + + return font; +} + +static void +setup_font_sample (GtkWidget *darea, + Antialiasing antialiasing, + Hinting hinting) +{ + const char *string1 = "abcfgop AO "; + const char *string2 = "abcfgop"; + + XftColor black = { 0, { 0, 0, 0, 0xffff } }; + XftColor white = { 0, { 0xffff, 0xffff, 0xffff, 0xffff } }; + + Display *xdisplay = gdk_x11_get_default_xdisplay (); + + GdkColormap *colormap = gdk_rgb_get_colormap (); + Colormap xcolormap = GDK_COLORMAP_XCOLORMAP (colormap); + + GdkVisual *visual = gdk_colormap_get_visual (colormap); + Visual *xvisual = GDK_VISUAL_XVISUAL (visual); + + FcPattern *pattern; + XftFont *font1, *font2; + XGlyphInfo extents1 = { 0 }; + XGlyphInfo extents2 = { 0 }; + GdkPixmap *pixmap; + XftDraw *draw; + GdkPixbuf *tmp_pixbuf, *pixbuf; + + int width, height; + int ascent, descent; + + pattern = FcPatternBuild (NULL, + FC_FAMILY, FcTypeString, "Serif", + FC_SLANT, FcTypeInteger, FC_SLANT_ROMAN, + FC_SIZE, FcTypeDouble, 20., + NULL); + font1 = open_pattern (pattern, antialiasing, hinting); + FcPatternDestroy (pattern); + + pattern = FcPatternBuild (NULL, + FC_FAMILY, FcTypeString, "Serif", + FC_SLANT, FcTypeInteger, FC_SLANT_ITALIC, + FC_SIZE, FcTypeDouble, 20., + NULL); + font2 = open_pattern (pattern, antialiasing, hinting); + FcPatternDestroy (pattern); + + if (font1) + XftTextExtentsUtf8 (xdisplay, font1, (char *)string1, strlen (string1), &extents1); + if (font2) + XftTextExtentsUtf8 (xdisplay, font2, (char *)string2, strlen (string2), &extents2); + + ascent = 0; + if (font1) + ascent = MAX (ascent, font1->ascent); + if (font2) + ascent = MAX (ascent, font2->ascent); + + descent = 0; + if (font1) + descent = MAX (descent, font1->descent); + if (font2) + descent = MAX (descent, font2->descent); + + width = extents1.xOff + extents2.xOff + 4; + + height = ascent + descent + 2; + + pixmap = gdk_pixmap_new (NULL, width, height, visual->depth); + + draw = XftDrawCreate (xdisplay, GDK_DRAWABLE_XID (pixmap), xvisual, xcolormap); + + XftDrawRect (draw, &white, 0, 0, width, height); + if (font1) + XftDrawStringUtf8 (draw, &black, font1, + 2, 2 + ascent, + (char *)string1, strlen (string1)); + if (font2) + XftDrawStringUtf8 (draw, &black, font2, + 2 + extents1.xOff, 2 + ascent, + (char *)string2, strlen (string2)); + + XftDrawDestroy (draw); + + if (font1) + XftFontClose (xdisplay, font1); + if (font2) + XftFontClose (xdisplay, font2); + + tmp_pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, colormap, 0, 0, 0, 0, width, height); + pixbuf = gdk_pixbuf_scale_simple (tmp_pixbuf, 1 * width, 1 * height, GDK_INTERP_TILES); + + g_object_unref (pixmap); + g_object_unref (tmp_pixbuf); + + g_object_set_data_full (G_OBJECT (darea), "sample-pixbuf", + pixbuf, (GDestroyNotify)g_object_unref); + + g_signal_connect (darea, "size_request", G_CALLBACK (sample_size_request), NULL); + g_signal_connect (darea, "expose_event", G_CALLBACK (sample_expose), NULL); +} + +/* + * Code implementing a group of radio buttons with different Xft option combinations. + * If one of the buttons is matched by the GConf key, we pick it. Otherwise we + * show the group as inconsistent. + */ +static void +font_render_get_gconf (Antialiasing *antialiasing, + Hinting *hinting) +{ + GConfClient *client = gconf_client_get_default (); + char *antialias_str = gconf_client_get_string (client, FONT_ANTIALIASING_KEY, NULL); + char *hint_str = gconf_client_get_string (client, FONT_HINTING_KEY, NULL); + int val; + + val = ANTIALIAS_GRAYSCALE; + if (antialias_str) + gconf_string_to_enum (antialias_enums, antialias_str, &val); + *antialiasing = val; + + val = HINT_FULL; + if (hint_str) + gconf_string_to_enum (hint_enums, hint_str, &val); + *hinting = val; +} + +typedef struct { + Antialiasing antialiasing; + Hinting hinting; + GtkWidget *radio; +} FontPair; + +static GSList *font_pairs = NULL; + +static void +font_render_load (void) +{ + Antialiasing antialiasing; + Hinting hinting; + gboolean inconsistent = TRUE; + GSList *tmp_list; + + font_render_get_gconf (&antialiasing, &hinting); + + in_change = TRUE; + + for (tmp_list = font_pairs; tmp_list; tmp_list = tmp_list->next) { + FontPair *pair = tmp_list->data; + + if (antialiasing == pair->antialiasing && hinting == pair->hinting) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pair->radio), TRUE); + inconsistent = FALSE; + } + } + + for (tmp_list = font_pairs; tmp_list; tmp_list = tmp_list->next) { + FontPair *pair = tmp_list->data; + + gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (pair->radio), inconsistent); + } + + in_change = FALSE; +} + +static void +font_render_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) +{ + font_render_load (); +} + +static void +font_radio_toggled (GtkToggleButton *toggle_button, + FontPair *pair) +{ + if (!in_change) { + GConfClient *client = gconf_client_get_default (); + + gconf_client_set_string (client, FONT_ANTIALIASING_KEY, + gconf_enum_to_string (antialias_enums, pair->antialiasing), + NULL); + gconf_client_set_string (client, FONT_HINTING_KEY, + gconf_enum_to_string (hint_enums, pair->hinting), + NULL); + } + + /* Restore back to the previous state until we get notification + */ + font_render_load (); +} + +static void +setup_font_pair (GtkWidget *radio, + GtkWidget *darea, + Antialiasing antialiasing, + Hinting hinting) +{ + FontPair *pair = g_new (FontPair, 1); + + pair->antialiasing = antialiasing; + pair->hinting = hinting; + pair->radio = radio; + + setup_font_sample (darea, antialiasing, hinting); + font_pairs = g_slist_prepend (font_pairs, pair); + + g_signal_connect (radio, "toggled", + G_CALLBACK (font_radio_toggled), pair); +} +#endif /* HAVE_XFT2 */ + static void setup_dialog (GladeXML *dialog) @@ -49,6 +409,9 @@ setup_dialog (GladeXML *dialog) client = gconf_client_get_default (); gconf_client_add_dir (client, "/desktop/gnome/interface", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); +#ifdef HAVE_XFT2 + gconf_client_add_dir (client, FONT_RENDER_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); +#endif /* HAVE_XFT2 */ peditor = gconf_peditor_new_font (NULL, GTK_FONT_KEY, WID ("application_font"), @@ -60,14 +423,286 @@ setup_dialog (GladeXML *dialog) widget = WID ("font_dialog"); capplet_set_icon (widget, "font-capplet.png"); - gtk_widget_show (widget); +#ifdef HAVE_XFT2 + setup_font_pair (WID ("monochrome_radio"), WID ("monochrome_sample"), ANTIALIAS_NONE, HINT_FULL); + setup_font_pair (WID ("best_shapes_radio"), WID ("best_shapes_sample"), ANTIALIAS_GRAYSCALE, HINT_MEDIUM); + setup_font_pair (WID ("best_contrast_radio"), WID ("best_contrast_sample"), ANTIALIAS_GRAYSCALE, HINT_FULL); + setup_font_pair (WID ("subpixel_radio"), WID ("subpixel_sample"), ANTIALIAS_RGBA, HINT_FULL); + + font_render_load (); + + gconf_client_notify_add (client, FONT_RENDER_DIR, + font_render_changed, + NULL, NULL, NULL); + + g_signal_connect (WID ("details_button"), + "clicked", + G_CALLBACK (cb_show_details), widget); +#else /* !HAVE_XFT2 */ + gtk_widget_hide (WID ("font_render_frame")); +#endif /* HAVE_XFT2 */ + g_signal_connect (G_OBJECT (widget), "response", G_CALLBACK (cb_dialog_response), NULL); + + gtk_widget_show (widget); +} + +#ifdef HAVE_XFT2 +/* + * EnumGroup - a group of radio buttons tied to a string enumeration + * value. We add this here because the gconf peditor + * equivalent of this is both painful to use (you have + * to supply functions to convert from enums to indices) + * and conceptually broken (the order of radio buttons + * in a group when using Glade is not predictable. + */ +typedef struct +{ + GConfClient *client; + GSList *items; + const gchar *gconf_key; + GConfEnumStringPair *enums; + int default_value; +} EnumGroup; + +typedef struct +{ + EnumGroup *group; + GtkWidget *widget; + int value; +} EnumItem; + +static void +enum_group_load (EnumGroup *group) +{ + char *str = gconf_client_get_string (group->client, group->gconf_key, NULL); + int val = group->default_value; + GSList *tmp_list; + + if (str) + gconf_string_to_enum (group->enums, str, &val); + + in_change = TRUE; + + for (tmp_list = group->items; tmp_list; tmp_list = tmp_list->next) { + EnumItem *item = tmp_list->data; + + if (val == item->value) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->widget), TRUE); + } + + + + in_change = FALSE; +} + +static void +enum_group_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) +{ + enum_group_load (user_data); +} + +static void +enum_item_toggled (GtkToggleButton *toggle_button, + EnumItem *item) +{ + EnumGroup *group = item->group; + + if (!in_change) { + gconf_client_set_string (group->client, group->gconf_key, + gconf_enum_to_string (group->enums, item->value), + NULL); + } + + /* Restore back to the previous state until we get notification + */ + enum_group_load (group); } -int +static EnumGroup * +enum_group_create (const gchar *gconf_key, + GConfEnumStringPair *enums, + int default_value, + GtkWidget *first_widget, + ...) +{ + EnumGroup *group; + GtkWidget *widget; + va_list args; + + group = g_new (EnumGroup, 1); + + group->client = gconf_client_get_default (); + group->gconf_key = g_strdup (gconf_key); + group->enums = enums; + group->default_value = default_value; + group->items = NULL; + + va_start (args, first_widget); + + widget = first_widget; + while (widget) + { + EnumItem *item; + + item = g_new (EnumItem, 1); + item->group = group; + item->widget = widget; + item->value = va_arg (args, int); + + g_signal_connect (item->widget, "toggled", + G_CALLBACK (enum_item_toggled), item); + + group->items = g_slist_prepend (group->items, item); + + widget = va_arg (args, GtkWidget *); + } + + va_end (args); + + enum_group_load (group); + + gconf_client_notify_add (group->client, gconf_key, + enum_group_changed, + group, NULL, NULL); + + return group; +} + +/* + * The font rendering details dialog + */ +static void +dpi_load (GConfClient *client, + GtkSpinButton *spinner) +{ + gdouble dpi = gconf_client_get_float (client, FONT_DPI_KEY, NULL); + + in_change = TRUE; + gtk_spin_button_set_value (spinner, dpi); + in_change = FALSE; +} + +static void +dpi_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) +{ + dpi_load (client, user_data); +} + +static void +dpi_value_changed (GtkSpinButton *spinner, + GConfClient *client) +{ + /* Like any time when using a spin button with GConf, there is + * a race condition here. When we change, we send the new + * value to GCOnf, then restore to the old value until + * we get a response to emulate the proper model/view behavior. + * + * If the user changes the value faster than responses are + * received from GConf, this may cause mild strange effects. + */ + gdouble new_dpi = gtk_spin_button_get_value (spinner); + + gconf_client_set_float (client, FONT_DPI_KEY, new_dpi, NULL); + + dpi_load (client, spinner); +} + +static void +cb_details_response (GtkDialog *dialog, gint response_id) +{ + if (response_id == GTK_RESPONSE_HELP) + capplet_help (GTK_WINDOW (dialog), + "wgoscustdesk.xml", + "goscustdesk-38"); + else + gtk_widget_hide (GTK_WIDGET (dialog)); +} + +static void +cb_show_details (GtkWidget *button, + GtkWindow *parent) +{ + static GtkWidget *details_dialog = NULL; + + if (!details_dialog) { + GConfClient *client = gconf_client_get_default (); + GladeXML *dialog = glade_xml_new (GLADEDIR "/font-properties.glade", "render_details", NULL); + GtkWidget *dpi_spinner; + + details_dialog = WID ("render_details"); + + gtk_window_set_transient_for (GTK_WINDOW (details_dialog), parent); + + dpi_spinner = WID ("dpi_spinner"); + dpi_load (client, GTK_SPIN_BUTTON (dpi_spinner)); + g_signal_connect (dpi_spinner, "value_changed", + G_CALLBACK (dpi_value_changed), client); + + gconf_client_notify_add (client, FONT_DPI_KEY, + dpi_changed, + dpi_spinner, NULL, NULL); + + setup_font_sample (WID ("antialias_none_sample"), ANTIALIAS_NONE, HINT_FULL); + setup_font_sample (WID ("antialias_grayscale_sample"), ANTIALIAS_GRAYSCALE, HINT_FULL); + setup_font_sample (WID ("antialias_subpixel_sample"), ANTIALIAS_RGBA, HINT_FULL); + + enum_group_create (FONT_ANTIALIASING_KEY, antialias_enums, ANTIALIAS_GRAYSCALE, + WID ("antialias_none_radio"), ANTIALIAS_NONE, + WID ("antialias_grayscale_radio"), ANTIALIAS_GRAYSCALE, + WID ("antialias_subpixel_radio"), ANTIALIAS_RGBA, + NULL); + + setup_font_sample (WID ("hint_none_sample"), ANTIALIAS_GRAYSCALE, HINT_NONE); + setup_font_sample (WID ("hint_slight_sample"), ANTIALIAS_GRAYSCALE, HINT_SLIGHT); + setup_font_sample (WID ("hint_medium_sample"), ANTIALIAS_GRAYSCALE, HINT_MEDIUM); + setup_font_sample (WID ("hint_full_sample"), ANTIALIAS_GRAYSCALE, HINT_FULL); + + enum_group_create (FONT_HINTING_KEY, hint_enums, HINT_FULL, + WID ("hint_none_radio"), HINT_NONE, + WID ("hint_slight_radio"), HINT_SLIGHT, + WID ("hint_medium_radio"), HINT_MEDIUM, + WID ("hint_full_radio"), HINT_FULL, + NULL); + + gtk_image_set_from_file (GTK_IMAGE (WID ("subpixel_rgb_image")), + PIXMAPDIR "/subpixel-rgb.png"); + gtk_image_set_from_file (GTK_IMAGE (WID ("subpixel_bgr_image")), + PIXMAPDIR "/subpixel-bgr.png"); + gtk_image_set_from_file (GTK_IMAGE (WID ("subpixel_vrgb_image")), + PIXMAPDIR "/subpixel-vrgb.png"); + gtk_image_set_from_file (GTK_IMAGE (WID ("subpixel_vbgr_image")), + PIXMAPDIR "/subpixel-vbgr.png"); + + enum_group_create (FONT_RGBA_ORDER_KEY, rgba_order_enums, RGBA_RGB, + WID ("subpixel_rgb_radio"), RGBA_RGB, + WID ("subpixel_bgr_radio"), RGBA_BGR, + WID ("subpixel_vrgb_radio"), RGBA_VRGB, + WID ("subpixel_vbgr_radio"), RGBA_VBGR, + NULL); + + g_signal_connect (G_OBJECT (details_dialog), + "response", + G_CALLBACK (cb_details_response), NULL); + g_signal_connect (G_OBJECT (details_dialog), + "delete_event", + G_CALLBACK (gtk_true), NULL); + } + + gtk_window_present (GTK_WINDOW (details_dialog)); +} +#endif /* HAVE_XFT2 */ + +t main (int argc, char *argv[]) { GladeXML *dialog; diff --git a/configure.in b/configure.in index d798bd9c0..4f57529e0 100644 --- a/configure.in +++ b/configure.in @@ -57,6 +57,21 @@ PKG_CHECK_MODULES(GNOME, libgnomeui-2.0) PKG_CHECK_MODULES(VFS_CAPPLET, $COMMON_MODULES gnome-vfs-module-2.0 gnome-vfs-2.0) PKG_CHECK_MODULES(SOUND_CAPPLET, esound) +dnl +dnl Check for Xft version 2; we build in extra functionality to the font capplet +dnl when we have it. +dnl +have_xft2=false +xft_modules="" +if $PKG_CONFIG --exists xft ; then + have_xft2=true + xft_modules="xft" +fi + +AC_DEFINE(HAVE_XFT2) + +PKG_CHECK_MODULES(FONT_CAPPLET, $COMMON_MODULES $xft_modules) + CAPPLET_LIBS="$CAPPLET_LIBS $x_libs" GNOMECC_LIBS="$GNOMECC_LIBS $x_libs" GNOME_SETTINGS_DAEMON_LIBS="$GNOME_SETTINGS_DAEMON_LIBS $x_libs" @@ -131,6 +146,9 @@ AC_SUBST(VFS_CAPPLET_LIBS) AC_SUBST(SOUND_CAPPLET_CFLAGS) AC_SUBST(SOUND_CAPPLET_LIBS) +AC_SUBST(FONT_CAPPLET_CFLAGS) +AC_SUBST(FONT_CAPPLET_LIBS) + AC_SUBST(GNOMECC_CFLAGS) AC_SUBST(GNOMECC_LIBS) diff --git a/gnome-settings-daemon/gnome-settings-xsettings.c b/gnome-settings-daemon/gnome-settings-xsettings.c index 8ff939b32..fa0023b7d 100644 --- a/gnome-settings-daemon/gnome-settings-xsettings.c +++ b/gnome-settings-daemon/gnome-settings-xsettings.c @@ -4,12 +4,24 @@ #include <glib.h> #include <libgnome/gnome-i18n.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + #include "gnome-settings-daemon.h" #include "gnome-settings-xsettings.h" #include "xsettings-manager.h" extern XSettingsManager *manager; +#ifdef HAVE_XFT2 +#define FONT_RENDER_DIR "/desktop/gnome/font_rendering" +#define FONT_ANTIALIASING_KEY FONT_RENDER_DIR "/antialiasing" +#define FONT_HINTING_KEY FONT_RENDER_DIR "/hinting" +#define FONT_RGBA_ORDER_KEY FONT_RENDER_DIR "/rgba_order" +#define FONT_DPI_KEY FONT_RENDER_DIR "/dpi" +#endif /* HAVE_XFT2 */ typedef struct _TranslationEntry TranslationEntry; typedef void (* TranslationFunc) (TranslationEntry *trans, @@ -23,6 +35,10 @@ struct _TranslationEntry TranslationFunc translate; }; +#ifdef HAVE_XFT2 +static void gnome_settings_update_xft (GConfClient *client); +static void xft_callback (GConfEntry *entry); +#endif /* HAVE_XFT2 */ static void translate_bool_int (TranslationEntry *trans, @@ -175,8 +191,284 @@ gnome_settings_xsettings_init (GConfClient *client) gnome_settings_daemon_register_callback ("/desktop/gnome/peripherals/mouse", xsettings_callback); gnome_settings_daemon_register_callback ("/desktop/gtk", xsettings_callback); gnome_settings_daemon_register_callback ("/desktop/gnome/interface", xsettings_callback); + +#ifdef HAVE_XFT2 + gnome_settings_daemon_register_callback (FONT_RENDER_DIR, xft_callback); +#endif /* HAVE_XFT2 */ } +#ifdef HAVE_XFT2 +static void +xft_callback (GConfEntry *entry) +{ + GConfClient *client; + + client = gconf_client_get_default (); + + gnome_settings_update_xft (client); + xsettings_manager_notify (manager); +} + +typedef struct +{ + gboolean antialias; + gboolean hinting; + int dpi; + const char *rgba; + const char *hintstyle; +} GnomeXftSettings; + +static const char *rgba_types[] = { "rgb", "bgr", "vbgr", "vrgb" }; + +/* Read GConf settings and determine the appropriate Xft settings based on them + * This probably could be done a bit more cleanly with gconf_string_to_enum + */ +static void +gnome_xft_settings_get (GConfClient *client, + GnomeXftSettings *settings) +{ + char *antialiasing = gconf_client_get_string (client, FONT_ANTIALIASING_KEY, NULL); + char *hinting = gconf_client_get_string (client, FONT_HINTING_KEY, NULL); + char *rgba_order = gconf_client_get_string (client, FONT_RGBA_ORDER_KEY, NULL); + double dpi = gconf_client_get_float (client, FONT_DPI_KEY, NULL); + + settings->antialias = TRUE; + settings->hinting = TRUE; + settings->hintstyle = "hintfull"; + settings->dpi = 96; + settings->rgba = "rgb"; + + if ((int)(1024 * dpi + 0.5) > 0) + settings->dpi = (int)(1024 * dpi + 0.5); + + if (rgba_order) + { + int i; + gboolean found = FALSE; + + for (i = 0; i < G_N_ELEMENTS (rgba_types) && !found; i++) + if (strcmp (rgba_order, rgba_types[i]) == 0) + { + settings->rgba = rgba_types[i]; + found = TRUE; + } + + if (!found) + g_warning ("Invalid value for " FONT_RGBA_ORDER_KEY ": '%s'", + rgba_order); + } + + if (hinting) + { + if (strcmp (hinting, "none") == 0) + { + settings->hinting = 0; + settings->hintstyle = "hintnone"; + } + else if (strcmp (hinting, "slight") == 0) + { + settings->hinting = 1; + settings->hintstyle = "hintslight"; + } + else if (strcmp (hinting, "medium") == 0) + { + settings->hinting = 1; + settings->hintstyle = "hintmedium"; + } + else if (strcmp (hinting, "full") == 0) + { + settings->hinting = 1; + settings->hintstyle = "hintfull"; + } + else + g_warning ("Invalid value for " FONT_HINTING_KEY ": '%s'", + hinting); + } + + if (antialiasing) + { + gboolean use_rgba = FALSE; + + if (strcmp (antialiasing, "none") == 0) + settings->antialias = 0; + else if (strcmp (antialiasing, "grayscale") == 0) + settings->antialias = 1; + else if (strcmp (antialiasing, "rgba") == 0) + { + settings->antialias = 1; + use_rgba = TRUE; + } + else + g_warning ("Invalid value for " FONT_ANTIALIASING_KEY " : '%s'", + antialiasing); + + if (!use_rgba) + settings->rgba = "none"; + } + + g_free (rgba_order); + g_free (hinting); + g_free (antialiasing); +} + +static void +gnome_xft_settings_set_xsettings (GnomeXftSettings *settings) +{ + xsettings_manager_set_int (manager, "Xft/Antialias", settings->antialias); + xsettings_manager_set_int (manager, "Xft/Hinting", settings->hinting); + xsettings_manager_set_string (manager, "Xft/HintStyle", settings->hintstyle); + xsettings_manager_set_int (manager, "Xft/DPI", settings->dpi); + xsettings_manager_set_string (manager, "Xft/RGBA", settings->rgba); +} + +/* + * Helper function for spawn_with_input() - write an entire + * string to a fd. + */ +static gboolean +write_all (int fd, + const char *buf, + gsize to_write) +{ + while (to_write > 0) + { + gssize count = write (fd, buf, to_write); + if (count < 0) + { + if (errno != EINTR) + return FALSE; + } + else + { + to_write -= count; + buf += count; + } + } + + return TRUE; +} + +/* + * Helper function for spawn_with_input() - wait for a child + * to exit. + */ +gboolean +wait_for_child (int pid, + int *status) +{ + gint ret; + + again: + ret = waitpid (pid, status, 0); + + if (ret < 0) + { + if (errno == EINTR) + goto again; + else + { + g_warning ("Unexpected error in waitpid() (%s)", + g_strerror (errno)); + return FALSE; + } + } + + return TRUE; +} + +/** + * spawn_with_input: + * @argv: command line to run + * @input: string to write to the child process. + * + * Spawns a child process specified by @argv, writes the text in + * @input to it, then waits for the child to exit. Any failures + * are output through g_warning(); if you wanted to use this in + * cases where errors need to be presented to the user, some + * modification would be needed. + **/ +static void +spawn_with_input (char **argv, + const char *input) +{ + int exit_status; + int child_pid; + int inpipe; + GError *err = NULL; + + if (!g_spawn_async_with_pipes (NULL /* working directory */, argv, NULL /* envp */, + G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, /* child setup and data */ + &child_pid, + &inpipe, NULL, NULL, /* stdin, stdout, stderr */ + &err)) + { + gchar *command = g_strjoinv (" ", argv); + g_warning ("Could not execute %s: %s", command, err->message); + g_error_free (err); + g_free (command); + + return; + } + + if (input) + { + if (!write_all (inpipe, input, strlen (input))) + { + gchar *command = g_strjoinv (" ", argv); + g_warning ("Could not write input to %s", command); + g_free (command); + } + + close (inpipe); + } + + wait_for_child (child_pid, &exit_status); + + if (!WIFEXITED (exit_status) || WEXITSTATUS (exit_status)) + { + gchar *command = g_strjoinv (" ", argv); + g_warning ("Command %s failed", command); + g_free (command); + } +} + +static void +gnome_xft_settings_set_xresources (GnomeXftSettings *settings) +{ + char *add[] = { "xrdb", "-merge", NULL }; + GString *add_string = g_string_new (NULL); + + g_string_append_printf (add_string, + "Xft.dpi: %f\n", settings->dpi / 1024.); + g_string_append_printf (add_string, + "Xft.antialias: %d\n", settings->antialias); + g_string_append_printf (add_string, + "Xft.hinting: %d\n", settings->hinting); + g_string_append_printf (add_string, + "Xft.hintstyle: %s\n", settings->hintstyle); + g_string_append_printf (add_string, + "Xft.rgba: %s\n", settings->rgba); + + spawn_with_input (add, add_string->str); + + g_string_free (add_string, TRUE); +} + +/* We mirror the Xft properties both through XSETTINGS and through + * X resources + */ +static void +gnome_settings_update_xft (GConfClient *client) +{ + GnomeXftSettings settings; + + gnome_xft_settings_get (client, &settings); + gnome_xft_settings_set_xsettings (&settings); + gnome_xft_settings_set_xresources (&settings); +} +#endif /* HAVE_XFT2 */ + void gnome_settings_xsettings_load (GConfClient *client) { @@ -207,5 +499,9 @@ gnome_settings_xsettings_load (GConfClient *client) ++i; } +#ifdef HAVE_XFT2 + gnome_settings_update_xft (client); +#endif /* HAVE_XFT */ + xsettings_manager_notify (manager); } diff --git a/schemas/Makefile.am b/schemas/Makefile.am index 4cf8b8b0d..fedae2498 100644 --- a/schemas/Makefile.am +++ b/schemas/Makefile.am @@ -1,7 +1,8 @@ schemadir = @GCONF_SCHEMA_FILE_DIR@ schema_DATA = \ apps_gnome_settings_daemon_screensaver.schemas \ - apps_gnome_settings_daemon_default_editor.schemas + apps_gnome_settings_daemon_default_editor.schemas \ + desktop_gnome_font_rendering.schemas schema_source_data = $(foreach file, $(schema_DATA), $(srcdir)/$(file)) diff --git a/schemas/desktop_gnome_font_rendering.schemas b/schemas/desktop_gnome_font_rendering.schemas new file mode 100644 index 000000000..dffd9bc30 --- /dev/null +++ b/schemas/desktop_gnome_font_rendering.schemas @@ -0,0 +1,69 @@ +<?xml version="1.0"?> +<gconfschemafile> + <schemalist> + <schema> + <key>/schemas/desktop/gnome/font_rendering/dpi</key> + <applyto>/desktop/gnome/font_rendering/dpi</applyto> + <owner>gnome</owner> + <type>float</type> + <default>96</default> + <locale name="C"> + <short>DPI</short> + <long> + Resolution used for converting font sizes to pixel sizes, + in dots per inch + </long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/gnome/font_rendering/antialiasing</key> + <applyto>/desktop/gnome/font_rendering/antialiasing</applyto> + <owner>gnome</owner> + <type>string</type> + <default>grayscale</default> + <locale name="C"> + <short>Antialising</short> + <long> + The type of antialiasing to use when rendering fonts. + Possible values are: "none" - no antialiasing. + "grayscale" - standard grayscale antialising. + "rgba" - subpixel antialising. (LCD screens only). + </long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/gnome/font_rendering/hinting</key> + <applyto>/desktop/gnome/font_rendering/hinting</applyto> + <owner>gnome</owner> + <type>string</type> + <default>medium</default> + <locale name="C"> + <short>Hinting</short> + <long> + The type of hinting to use when rendering fonts. + Possible values are: "none" - no hinting, + "slight", "medium", and + "full" - as much hinting as possible; may cause + distortion of letter forms. + </long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/gnome/font_rendering/rgba_order</key> + <applyto>/desktop/gnome/font_rendering/rgba_order</applyto> + <owner>gnome</owner> + <type>string</type> + <default>rgb</default> + <locale name="C"> + <short>RGBA Order</short> + <long> + The order of elements subpixel elements on an LCD + screen; only used when antialising is set to "rgba". + Possible values are: "rgb" - red on left, most common. + "bgr" - blue on left. "vrgb" - red on top. "vbgr" - + red on bottom. + </long> + </locale> + </schema> + </schemalist> +</gconfschemafile> |