1 /* GDK - The GIMP Drawing Kit
2  * Copyright © 2005 Red Hat, Inc
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Based on code from xftdpy.c
18  *
19  * Copyright © 2000 Keith Packard
20  *
21  * Permission to use, copy, modify, distribute, and sell this software and its
22  * documentation for any purpose is hereby granted without fee, provided that
23  * the above copyright notice appear in all copies and that both that
24  * copyright notice and this permission notice appear in supporting
25  * documentation, and that the name of Keith Packard not be used in
26  * advertising or publicity pertaining to distribution of the software without
27  * specific, written prior permission.  Keith Packard makes no
28  * representations about the suitability of this software for any purpose.  It
29  * is provided "as is" without express or implied warranty.
30  *
31  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
32  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
33  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
34  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
35  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
36  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
37  * PERFORMANCE OF THIS SOFTWARE.
38  */
39 
40 #include "config.h"
41 
42 #include <stdlib.h>
43 #include <string.h>
44 
45 #include <fontconfig/fontconfig.h>
46 
47 #ifndef FC_HINT_STYLE
48 #define FC_HINT_NONE        0
49 #define FC_HINT_SLIGHT      1
50 #define FC_HINT_MEDIUM      2
51 #define FC_HINT_FULL        3
52 #endif
53 
54 #include <gdkscreen-x11.h>
55 #include <gdkprivate-x11.h>
56 
57 static gint
parse_boolean(char * v)58 parse_boolean (char *v)
59 {
60   gchar c0, c1;
61 
62   c0 = *v;
63   if (g_ascii_isupper ((int)c0))
64     c0 = g_ascii_tolower (c0);
65   if (c0 == 't' || c0 == 'y' || c0 == '1')
66     return 1;
67   if (c0 == 'f' || c0 == 'n' || c0 == '0')
68     return 0;
69   if (c0 == 'o')
70     {
71       c1 = v[1];
72       if (g_ascii_isupper ((int)c1))
73 	c1 = g_ascii_tolower (c1);
74       if (c1 == 'n')
75 	return 1;
76       if (c1 == 'f')
77 	return 0;
78     }
79 
80   return -1;
81 }
82 
83 static gboolean
get_boolean_default(Display * dpy,gchar * option,gboolean * value)84 get_boolean_default (Display *dpy,
85 		     gchar   *option,
86 		     gboolean *value)
87 {
88   gchar *v;
89   gint i;
90 
91   v = XGetDefault (dpy, "Xft", option);
92   if (v)
93     {
94       i = parse_boolean (v);
95       if (i >= 0)
96 	{
97 	  *value = i;
98 	  return TRUE;
99 	}
100     }
101 
102   return FALSE;
103 }
104 
105 static gboolean
get_double_default(Display * dpy,gchar * option,gdouble * value)106 get_double_default (Display *dpy,
107 		    gchar   *option,
108 		    gdouble *value)
109 {
110   gchar    *v, *e;
111 
112   v = XGetDefault (dpy, "Xft", option);
113   if (v)
114     {
115       /* Xft uses strtod, though localization probably wasn't
116        * desired. For compatibility, we use the conservative
117        * g_strtod() that accepts either localized or non-localized
118        * decimal separator.
119        */
120       *value = g_strtod (v, &e);
121       if (e != v)
122 	return TRUE;
123     }
124 
125   return FALSE;
126 }
127 
128 static gboolean
get_integer_default(Display * dpy,gchar * option,gint * value)129 get_integer_default (Display *dpy,
130 		     gchar   *option,
131 		     gint    *value)
132 {
133   gchar *v, *e;
134 
135   v = XGetDefault (dpy, "Xft", option);
136   if (v)
137     {
138       if (FcNameConstant ((FcChar8 *) v, value))
139 	return TRUE;
140 
141       *value = strtol (v, &e, 0);
142       if (e != v)
143 	return TRUE;
144     }
145 
146   return FALSE;
147 }
148 
149 static void
init_xft_settings(GdkScreen * screen)150 init_xft_settings (GdkScreen *screen)
151 {
152   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
153   Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
154   double dpi_double;
155   gboolean b;
156 
157   if (x11_screen->xft_init)
158     return;
159 
160   x11_screen->xft_init = TRUE;
161 
162   if (!get_boolean_default (xdisplay, "antialias", &b))
163     b = TRUE;
164   x11_screen->xft_antialias = b;
165 
166   if (!get_boolean_default (xdisplay, "hinting", &b))
167     b = TRUE;
168   x11_screen->xft_hinting = b;
169 
170   if (!get_integer_default (xdisplay, "hintstyle", &x11_screen->xft_hintstyle))
171     x11_screen->xft_hintstyle = FC_HINT_MEDIUM;
172 
173   if (!get_integer_default (xdisplay, "rgba", &x11_screen->xft_rgba))
174     x11_screen->xft_rgba = FC_RGBA_UNKNOWN;
175 
176   if (!get_double_default (xdisplay, "dpi", &dpi_double))
177     dpi_double = 96.0;
178 
179   x11_screen->xft_dpi = (int)(0.5 + PANGO_SCALE * dpi_double);
180 }
181 
182 gboolean
_gdk_x11_get_xft_setting(GdkScreen * screen,const gchar * name,GValue * value)183 _gdk_x11_get_xft_setting (GdkScreen   *screen,
184 			  const gchar *name,
185 			  GValue      *value)
186 {
187   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
188 
189   if (strncmp (name, "gtk-xft-", 8) != 0)
190     return FALSE;
191 
192   name += 8;
193 
194   init_xft_settings (screen);
195 
196   if (strcmp (name, "antialias") == 0)
197     {
198       g_value_set_int (value, x11_screen->xft_antialias);
199       return TRUE;
200     }
201   else if (strcmp (name, "hinting") == 0)
202     {
203       g_value_set_int (value, x11_screen->xft_hinting);
204       return TRUE;
205     }
206   else if (strcmp (name, "hintstyle") == 0)
207     {
208       const char *str;
209 
210       switch (x11_screen->xft_hintstyle)
211 	{
212 	case FC_HINT_NONE:
213 	  str = "hintnone";
214 	  break;
215 	case FC_HINT_SLIGHT:
216 	  str = "hintslight";
217 	  break;
218 	case FC_HINT_MEDIUM:
219 	  str = "hintmedium";
220 	  break;
221 	case FC_HINT_FULL:
222 	  str = "hintfull";
223 	  break;
224 	default:
225 	  return FALSE;
226 	}
227 
228       g_value_set_string (value, str);
229       return TRUE;
230     }
231   else if (strcmp (name, "rgba") == 0)
232     {
233       const char *str;
234 
235       switch (x11_screen->xft_rgba)
236 	{
237 	case FC_RGBA_NONE:
238 	  str = "none";
239 	  break;
240 	case FC_RGBA_RGB:
241 	  str = "rgb";
242 	  break;
243 	case FC_RGBA_BGR:
244 	  str = "bgr";
245 	  break;
246 	case FC_RGBA_VRGB:
247 	  str = "vrgb";
248 	  break;
249 	case FC_RGBA_VBGR:
250 	  str = "vbgr";
251 	  break;
252 	case FC_RGBA_UNKNOWN:
253 	default:
254 	  return FALSE;
255 	}
256 
257       g_value_set_string (value, str);
258       return TRUE;
259    }
260   else if (strcmp (name, "dpi") == 0)
261     {
262       g_value_set_int (value, x11_screen->xft_dpi);
263       return TRUE;
264     }
265 
266   return FALSE;
267 }
268