Fix bug in _cairo_gl_has_extension
[platform/core/graphics/cairo.git] / src / cairo-xcb-resources.c
1 /* Cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2014 Lukas Lalinsky
4  * Copyright © 2005 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it either under the terms of the GNU Lesser General Public
8  * License version 2.1 as published by the Free Software Foundation
9  * (the "LGPL") or, at your option, under the terms of the Mozilla
10  * Public License Version 1.1 (the "MPL"). If you do not alter this
11  * notice, a recipient may use your version of this file under either
12  * the MPL or the LGPL.
13  *
14  * You should have received a copy of the LGPL along with this library
15  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17  * You should have received a copy of the MPL along with this library
18  * in the file COPYING-MPL-1.1
19  *
20  * The contents of this file are subject to the Mozilla Public License
21  * Version 1.1 (the "License"); you may not use this file except in
22  * compliance with the License. You may obtain a copy of the License at
23  * http://www.mozilla.org/MPL/
24  *
25  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27  * the specific language governing rights and limitations.
28  *
29  * Authors:
30  *    Lukas Lalinsky <lukas@oxygene.sk>
31  *
32  * Partially on code from xftdpy.c
33  *
34  * Copyright © 2000 Keith Packard
35  *
36  * Permission to use, copy, modify, distribute, and sell this software and its
37  * documentation for any purpose is hereby granted without fee, provided that
38  * the above copyright notice appear in all copies and that both that
39  * copyright notice and this permission notice appear in supporting
40  * documentation, and that the name of Keith Packard not be used in
41  * advertising or publicity pertaining to distribution of the software without
42  * specific, written prior permission.  Keith Packard makes no
43  * representations about the suitability of this software for any purpose.  It
44  * is provided "as is" without express or implied warranty.
45  *
46  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
47  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
48  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
49  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
50  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
51  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
52  * PERFORMANCE OF THIS SOFTWARE.
53  */
54
55 #include "cairoint.h"
56
57 #include "cairo-xcb-private.h"
58
59 #include "cairo-fontconfig-private.h"
60
61 static void
62 parse_boolean (const char *v, cairo_bool_t *out)
63 {
64     char c0, c1;
65
66     c0 = *v;
67     if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1')
68         *out = TRUE;
69     if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0')
70         *out = FALSE;
71     if (c0 == 'o') {
72         c1 = v[1];
73         if (c1 == 'n' || c1 == 'N')
74             *out = TRUE;
75         if (c1 == 'f' || c1 == 'F')
76             *out = FALSE;
77     }
78 }
79
80 static void
81 parse_integer (const char *v, int *out)
82 {
83     char *e;
84     int value;
85
86 #if CAIRO_HAS_FC_FONT
87     if (FcNameConstant ((FcChar8 *) v, out))
88         return;
89 #endif
90
91     value = strtol (v, &e, 0);
92     if (e != v)
93         *out = value;
94 }
95
96 static char *
97 skip_spaces(char *str)
98 {
99     while (*str == ' ' || *str == '\t' || *str == '\n')
100         str++;
101     return str;
102 }
103
104 struct resource_parser {
105     int buffer_size;
106     int bytes_in_buffer;
107     char* buffer;
108     cairo_xcb_resources_t *resources;
109 };
110
111 static cairo_bool_t
112 resource_parse_line (char *name, cairo_xcb_resources_t *resources)
113 {
114     char *value;
115
116     value = strchr (name, ':');
117     if (value == NULL)
118         return FALSE;
119
120     *value++ = 0;
121
122     name = skip_spaces (name);
123     value = skip_spaces (value);
124
125     if (strcmp (name, "Xft.antialias") == 0)
126         parse_boolean (value, &(resources->xft_antialias));
127     else if (strcmp (name, "Xft.lcdfilter") == 0)
128         parse_integer (value, &(resources->xft_lcdfilter));
129     else if (strcmp (name, "Xft.rgba") == 0)
130         parse_integer (value, &(resources->xft_rgba));
131     else if (strcmp (name, "Xft.hinting") == 0)
132         parse_boolean (value, &(resources->xft_hinting));
133     else if (strcmp (name, "Xft.hintstyle") == 0)
134         parse_integer (value, &(resources->xft_hintstyle));
135
136     return TRUE;
137 }
138
139 static int
140 resource_parse_lines (struct resource_parser *parser)
141 {
142     char *line, *newline;
143
144     line = parser->buffer;
145     while (1) {
146         newline = strchr (line, '\n');
147         if (newline == NULL)
148             break;
149
150         *newline++ = 0;
151
152         if (! resource_parse_line (line, parser->resources))
153             break;
154
155         line = newline;
156     }
157
158     return line - parser->buffer;
159 }
160
161 static void
162 resource_parser_init (struct resource_parser *parser, cairo_xcb_resources_t *resources)
163 {
164     parser->buffer_size = 0;
165     parser->bytes_in_buffer = 0;
166     parser->buffer = NULL;
167     parser->resources = resources;
168 }
169
170 static cairo_bool_t
171 resource_parser_update (struct resource_parser *parser, const char *data, int length)
172 {
173     int bytes_parsed;
174
175     if (parser->bytes_in_buffer + length + 1 > parser->buffer_size) {
176         parser->buffer_size = parser->bytes_in_buffer + length + 1;
177         parser->buffer = realloc(parser->buffer, parser->buffer_size);
178         if (! parser->buffer) {
179             parser->buffer_size = 0;
180             parser->bytes_in_buffer = 0;
181             return FALSE;
182         }
183     }
184
185     memmove (parser->buffer + parser->bytes_in_buffer, data, length);
186     parser->bytes_in_buffer += length;
187     parser->buffer[parser->bytes_in_buffer] = 0;
188
189     bytes_parsed = resource_parse_lines (parser);
190
191     if (parser->bytes_in_buffer > bytes_parsed) {
192         memmove (parser->buffer, parser->buffer + bytes_parsed, parser->bytes_in_buffer - bytes_parsed);
193         parser->bytes_in_buffer -= bytes_parsed;
194     } else {
195         parser->bytes_in_buffer = 0;
196     }
197
198     return TRUE;
199 }
200
201 static void
202 resource_parser_done (struct resource_parser *parser)
203 {
204     if (parser->bytes_in_buffer > 0) {
205         parser->buffer[parser->bytes_in_buffer] = 0;
206         resource_parse_line (parser->buffer, parser->resources);
207     }
208
209     free (parser->buffer);
210 }
211
212 static void
213 get_resources(xcb_connection_t *connection, xcb_screen_t *screen, cairo_xcb_resources_t *resources)
214 {
215     xcb_get_property_cookie_t cookie;
216     xcb_get_property_reply_t *reply;
217     struct resource_parser parser;
218     int offset;
219     cairo_bool_t has_more_data;
220
221     resources->xft_antialias = TRUE;
222     resources->xft_lcdfilter = -1;
223     resources->xft_hinting = TRUE;
224     resources->xft_hintstyle = FC_HINT_FULL;
225     resources->xft_rgba = FC_RGBA_UNKNOWN;
226
227     resource_parser_init (&parser, resources);
228
229     offset = 0;
230     has_more_data = FALSE;
231     do {
232         cookie = xcb_get_property (connection, 0, screen->root, XCB_ATOM_RESOURCE_MANAGER, XCB_ATOM_STRING, offset, 1024);
233         reply = xcb_get_property_reply (connection, cookie, NULL);
234
235         if (reply) {
236             if (reply->format == 8 && reply->type == XCB_ATOM_STRING) {
237                 char *value = (char *) xcb_get_property_value (reply);
238                 int length = xcb_get_property_value_length (reply);
239
240                 offset += length / 4; /* X needs the offset in 'long' units */
241                 has_more_data = reply->bytes_after > 0;
242
243                 if (! resource_parser_update (&parser, value, length))
244                     has_more_data = FALSE; /* early exit on error */
245             }
246
247             free (reply);
248         }
249     } while (has_more_data);
250
251     resource_parser_done (&parser);
252 }
253
254 void
255 _cairo_xcb_resources_get (cairo_xcb_screen_t *screen, cairo_xcb_resources_t *resources)
256 {
257     get_resources (screen->connection->xcb_connection, screen->xcb_screen, resources);
258
259     if (resources->xft_rgba == FC_RGBA_UNKNOWN) {
260         switch (screen->subpixel_order) {
261         case XCB_RENDER_SUB_PIXEL_UNKNOWN:
262             resources->xft_rgba = FC_RGBA_UNKNOWN;
263             break;
264         case XCB_RENDER_SUB_PIXEL_HORIZONTAL_RGB:
265             resources->xft_rgba = FC_RGBA_RGB;
266             break;
267         case XCB_RENDER_SUB_PIXEL_HORIZONTAL_BGR:
268             resources->xft_rgba = FC_RGBA_BGR;
269             break;
270         case XCB_RENDER_SUB_PIXEL_VERTICAL_RGB:
271             resources->xft_rgba = FC_RGBA_VRGB;
272             break;
273         case XCB_RENDER_SUB_PIXEL_VERTICAL_BGR:
274             resources->xft_rgba = FC_RGBA_VBGR;
275             break;
276         case XCB_RENDER_SUB_PIXEL_NONE:
277             resources->xft_rgba = FC_RGBA_NONE;
278             break;
279         }
280     }
281 }