]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkxftdefaults.c
4accd9d351ab4d7d1104e0639e3109b2201c449e
[~andy/gtk] / gdk / x11 / gdkxftdefaults.c
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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Based on code from xftdpy.c
20  *
21  * Copyright © 2000 Keith Packard
22  *
23  * Permission to use, copy, modify, distribute, and sell this software and its
24  * documentation for any purpose is hereby granted without fee, provided that
25  * the above copyright notice appear in all copies and that both that
26  * copyright notice and this permission notice appear in supporting
27  * documentation, and that the name of Keith Packard not be used in
28  * advertising or publicity pertaining to distribution of the software without
29  * specific, written prior permission.  Keith Packard makes no
30  * representations about the suitability of this software for any purpose.  It
31  * is provided "as is" without express or implied warranty.
32  *
33  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
34  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
35  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
36  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
37  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39  * PERFORMANCE OF THIS SOFTWARE.
40  */
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include <fontconfig/fontconfig.h>
45
46 #ifndef FC_HINT_STYLE
47 #define FC_HINT_NONE        0
48 #define FC_HINT_SLIGHT      1
49 #define FC_HINT_MEDIUM      2
50 #define FC_HINT_FULL        3
51 #endif
52
53 #include <gdkscreen-x11.h>
54 #include <gdkx.h>
55
56 static gint
57 parse_boolean (char *v)
58 {
59   gchar c0, c1;
60   
61   c0 = *v;
62   if (g_ascii_isupper ((int)c0))
63     c0 = g_ascii_tolower (c0);
64   if (c0 == 't' || c0 == 'y' || c0 == '1')
65     return 1;
66   if (c0 == 'f' || c0 == 'n' || c0 == '0')
67     return 0;
68   if (c0 == 'o')
69     {
70       c1 = v[1];
71       if (g_ascii_isupper ((int)c1))
72         c1 = g_ascii_tolower (c1);
73       if (c1 == 'n')
74         return 1;
75       if (c1 == 'f')
76         return 0;
77     }
78   
79   return -1;
80 }
81
82 static gboolean
83 get_boolean_default (Display *dpy,
84                      gchar   *option,
85                      gboolean *value)
86 {
87   gchar *v;
88   gint i;
89   
90   v = XGetDefault (dpy, "Xft", option);
91   if (v)
92     {
93       i = parse_boolean (v);
94       if (i >= 0)
95         {
96           *value = i;
97           return TRUE;
98         }
99     }
100   
101   return FALSE;
102 }
103
104 static gboolean
105 get_double_default (Display *dpy,
106                     gchar   *option,
107                     gdouble *value)
108 {
109   gchar    *v, *e;
110   
111   v = XGetDefault (dpy, "Xft", option);
112   if (v)
113     {
114       /* Xft uses strtod, though localization probably wasn't
115        * desired. For compatibility, we use the conservative
116        * g_strtod() that accepts either localized or non-localized
117        * decimal separator.
118        */
119       *value = g_strtod (v, &e);
120       if (e != v)
121         return TRUE;
122     }
123   
124   return FALSE;
125 }
126
127 static gboolean
128 get_integer_default (Display *dpy,
129                      gchar   *option,
130                      gint    *value)
131 {
132   gint i;
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       i = strtol (v, &e, 0);
142       if (e != v)
143         return TRUE;
144     }
145   
146   return FALSE;
147 }
148
149 static void
150 init_xft_settings (GdkScreen *screen)
151 {
152   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
153   Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
154   int xscreen = GDK_SCREEN_XNUMBER (screen);
155   double dpi_double;
156
157   if (screen_x11->xft_init)
158     return;
159
160   screen_x11->xft_init = TRUE;
161
162   if (!get_boolean_default (xdisplay, "antialias", &screen_x11->xft_antialias))
163     screen_x11->xft_antialias = TRUE;
164
165   if (!get_boolean_default (xdisplay, "hinting", &screen_x11->xft_hinting))
166     screen_x11->xft_hinting = TRUE;
167
168   if (!get_integer_default (xdisplay, "hintstyle", &screen_x11->xft_hintstyle))
169     screen_x11->xft_hintstyle = FC_HINT_FULL;
170
171   if (!get_integer_default (xdisplay, "rgba", &screen_x11->xft_rgba))
172                             
173     {
174       int subpixel = FC_RGBA_UNKNOWN;
175       
176 #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
177       if (_gdk_x11_have_render (screen_x11->display))
178         {
179           int render_order = XRenderQuerySubpixelOrder (xdisplay, xscreen);
180           
181           switch (render_order)
182             {
183             default:
184             case SubPixelUnknown:
185               subpixel = FC_RGBA_UNKNOWN;
186               break;
187             case SubPixelHorizontalRGB:
188               subpixel = FC_RGBA_RGB;
189               break;
190             case SubPixelHorizontalBGR:
191               subpixel = FC_RGBA_BGR;
192               break;
193             case SubPixelVerticalRGB:
194               subpixel = FC_RGBA_VRGB;
195               break;
196             case SubPixelVerticalBGR:
197               subpixel = FC_RGBA_VBGR;
198               break;
199             case SubPixelNone:
200               subpixel = FC_RGBA_NONE;
201               break;
202             }
203         }
204
205       screen_x11->xft_rgba = subpixel;
206 #endif
207     }
208
209   if (!get_double_default (xdisplay, "dpi", &dpi_double))
210     dpi_double = (((double) DisplayHeight (xdisplay, xscreen) * 25.4) / 
211                   (double) DisplayHeightMM (xdisplay, xscreen));
212
213   screen_x11->xft_dpi = (int)(0.5 + PANGO_SCALE * dpi_double);
214 }
215
216 gboolean
217 _gdk_x11_get_xft_setting (GdkScreen   *screen,
218                           const gchar *name,
219                           GValue      *value)
220 {
221   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
222   
223   if (strncmp (name, "gtk-xft-", 8) != 0)
224     return FALSE;
225
226   name += 8;
227
228   init_xft_settings (screen);
229
230   if (strcmp (name, "antialias") == 0)
231     {
232       g_value_set_int (value, screen_x11->xft_antialias);
233       return TRUE;
234     }
235   else if (strcmp (name, "hinting") == 0)
236     {
237       g_value_set_int (value, screen_x11->xft_hinting);
238       return TRUE;
239     }
240   else if (strcmp (name, "hintstyle") == 0)
241     {
242       const char *str;
243       
244       switch (screen_x11->xft_hintstyle)
245         {
246         case FC_HINT_NONE:
247           str = "hintnone";
248           break;
249         case FC_HINT_SLIGHT:
250           str = "hintslight";
251           break;
252         case FC_HINT_MEDIUM:
253           str = "hintmedium";
254           break;
255         case FC_HINT_FULL:
256           str = "hintfull";
257           break;
258         default:
259           return FALSE;
260         }
261
262       g_value_set_string (value, str);
263       return TRUE;
264     }
265   else if (strcmp (name, "rgba") == 0)
266     {
267       const char *str;
268       
269       switch (screen_x11->xft_rgba)
270         {
271         case FC_RGBA_NONE:
272           str = "none";
273           break;
274         case FC_RGBA_RGB:
275           str = "rgb";
276           break;
277         case FC_RGBA_BGR:
278           str = "bgr";
279           break;
280         case FC_RGBA_VRGB:
281           str = "vrgb";
282           break;
283         case FC_RGBA_VBGR:
284           str = "vbgr";
285           break;
286         case FC_RGBA_UNKNOWN:
287         default:
288           return FALSE;
289         }
290         
291       g_value_set_string (value, str);
292       return TRUE; 
293    }
294   else if (strcmp (name, "dpi") == 0)
295     {
296       g_value_set_int (value, screen_x11->xft_dpi);
297       return TRUE;
298     }
299
300   return FALSE;
301 }