[cairo-commit] src/Makefile.sources src/cairo-xcb-private.h src/cairo-xcb-resources.c src/cairo-xcb-screen.c src/cairo-xcb-surface.c

Uli Schlachter psychon at kemper.freedesktop.org
Fri Sep 12 09:22:05 PDT 2014


 src/Makefile.sources      |    1 
 src/cairo-xcb-private.h   |   19 ++
 src/cairo-xcb-resources.c |  304 ++++++++++++++++++++++++++++++++++++++++++++++
 src/cairo-xcb-screen.c    |  108 ++++++++++++++++
 src/cairo-xcb-surface.c   |    6 
 5 files changed, 435 insertions(+), 3 deletions(-)

New commits:
commit e691d242d592a8556e25659fb091a2031abee4c9
Author: Lukáš Lalinský <lukas at oxygene.sk>
Date:   Wed Sep 3 22:53:55 2014 +0200

    xcb: Initialize font options from Xft resources
    
    There is a similar code in the Xlib backend. The logic here is the same, but
    XCB doesn't support X resources directly, so there is some custom code
    to get and parse the resources from the root window.
    
    Signed-off-by: Lukáš Lalinský <lukas at oxygene.sk>
    Reviewed-by: Uli Schlachter <psychon at znc.in>

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 2e14fff..c946cad 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -334,6 +334,7 @@ cairo_xcb_sources = \
 		    cairo-xcb-surface.c \
 		    cairo-xcb-surface-core.c \
 		    cairo-xcb-surface-render.c \
+		    cairo-xcb-resources.c \
 		    $(NULL)
 
 cairo_qt_headers = cairo-qt.h
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index 134100a..2610458 100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -75,6 +75,7 @@ typedef struct _cairo_xcb_surface cairo_xcb_surface_t;
 typedef struct _cairo_xcb_picture cairo_xcb_picture_t;
 typedef struct _cairo_xcb_shm_mem_pool cairo_xcb_shm_mem_pool_t;
 typedef struct _cairo_xcb_shm_info cairo_xcb_shm_info_t;
+typedef struct _cairo_xcb_resources cairo_xcb_resources_t;
 
 struct _cairo_xcb_shm_info {
     cairo_xcb_connection_t *connection;
@@ -199,6 +200,9 @@ struct _cairo_xcb_screen {
     cairo_list_t link;
     cairo_list_t surfaces;
     cairo_list_t pictures;
+
+    cairo_bool_t has_font_options;
+    cairo_font_options_t font_options;
 };
 
 struct _cairo_xcb_connection {
@@ -236,6 +240,14 @@ struct _cairo_xcb_connection {
     cairo_list_t link;
 };
 
+struct _cairo_xcb_resources {
+    cairo_bool_t xft_antialias;
+    int xft_lcdfilter;
+    cairo_bool_t xft_hinting;
+    int xft_hintstyle;
+    int xft_rgba;
+};
+
 enum {
     CAIRO_XCB_HAS_RENDER			= 0x0001,
     CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES	= 0x0002,
@@ -357,6 +369,9 @@ _cairo_xcb_screen_get_gc (cairo_xcb_screen_t *screen,
 cairo_private void
 _cairo_xcb_screen_put_gc (cairo_xcb_screen_t *screen, int depth, xcb_gcontext_t gc);
 
+cairo_private cairo_font_options_t *
+_cairo_xcb_screen_get_font_options (cairo_xcb_screen_t *screen);
+
 cairo_private cairo_status_t
 _cairo_xcb_screen_store_linear_picture (cairo_xcb_screen_t *screen,
 					const cairo_linear_pattern_t *linear,
@@ -773,4 +788,8 @@ slim_hidden_proto_no_warn (cairo_xcb_device_debug_set_precision);
 slim_hidden_proto_no_warn (cairo_xcb_device_debug_cap_xrender_version);
 #endif
 
+cairo_private void
+_cairo_xcb_resources_get (cairo_xcb_screen_t *screen,
+			  cairo_xcb_resources_t *resources);
+
 #endif /* CAIRO_XCB_PRIVATE_H */
diff --git a/src/cairo-xcb-resources.c b/src/cairo-xcb-resources.c
new file mode 100644
index 0000000..62c27ef
--- /dev/null
+++ b/src/cairo-xcb-resources.c
@@ -0,0 +1,304 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2014 Lukas Lalinsky
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * Authors:
+ *    Lukas Lalinsky <lukas at oxygene.sk>
+ *
+ * Partially on code from xftdpy.c
+ *
+ * Copyright © 2000 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cairoint.h"
+
+#include "cairo-xcb-private.h"
+
+#include "cairo-fontconfig-private.h"
+
+static void
+parse_boolean (const char *v, cairo_bool_t *out)
+{
+    char c0, c1;
+
+    c0 = *v;
+    if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1')
+	*out = TRUE;
+    if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0')
+	*out = FALSE;
+    if (c0 == 'o') {
+	c1 = v[1];
+	if (c1 == 'n' || c1 == 'N')
+	    *out = TRUE;
+	if (c1 == 'f' || c1 == 'F')
+	    *out = FALSE;
+    }
+}
+
+static void
+parse_integer (const char *v, int *out)
+{
+    char *e;
+    int value;
+
+#if CAIRO_HAS_FC_FONT
+    if (FcNameConstant ((FcChar8 *) v, out))
+	return;
+#endif
+
+    value = strtol (v, &e, 0);
+    if (e != v)
+	*out = value;
+}
+
+static char *
+skip_spaces(char *str)
+{
+    while (*str == ' ' || *str == '\t' || *str == '\n')
+	str++;
+    return str;
+}
+
+struct resource_parser {
+    int buffer_size;
+    int bytes_in_buffer;
+    char* buffer;
+    cairo_xcb_resources_t *resources;
+};
+
+static cairo_bool_t
+resource_parse_line (char *name, cairo_xcb_resources_t *resources)
+{
+    char *value;
+
+    value = strchr (name, ':');
+    if (value == NULL)
+	return FALSE;
+
+    *value++ = 0;
+
+    name = skip_spaces (name);
+    value = skip_spaces (value);
+
+    if (strcmp (name, "Xft.antialias") == 0)
+	parse_boolean (value, &(resources->xft_antialias));
+    else if (strcmp (name, "Xft.lcdfilter") == 0)
+	parse_integer (value, &(resources->xft_lcdfilter));
+    else if (strcmp (name, "Xft.rgba") == 0)
+	parse_integer (value, &(resources->xft_rgba));
+    else if (strcmp (name, "Xft.hinting") == 0)
+	parse_boolean (value, &(resources->xft_hinting));
+    else if (strcmp (name, "Xft.hintstyle") == 0)
+	parse_integer (value, &(resources->xft_hintstyle));
+
+    return TRUE;
+}
+
+static int
+resource_parse_lines (struct resource_parser *parser)
+{
+    char *line, *newline;
+
+    line = parser->buffer;
+    while (1) {
+	newline = strchr (line, '\n');
+	if (newline == NULL)
+	    break;
+
+	*newline++ = 0;
+
+	if (! resource_parse_line (line, parser->resources))
+	    break;
+
+	line = newline;
+    }
+
+    return line - parser->buffer;
+}
+
+static void
+resource_parser_init (struct resource_parser *parser, cairo_xcb_resources_t *resources)
+{
+    parser->buffer_size = 0;
+    parser->bytes_in_buffer = 0;
+    parser->buffer = NULL;
+    parser->resources = resources;
+}
+
+static cairo_bool_t
+resource_parser_update (struct resource_parser *parser, const char *data, int length)
+{
+    int bytes_parsed;
+
+    if (parser->bytes_in_buffer + length + 1 > parser->buffer_size) {
+	parser->buffer_size = parser->bytes_in_buffer + length + 1;
+	parser->buffer = realloc(parser->buffer, parser->buffer_size);
+	if (! parser->buffer) {
+	    parser->buffer_size = 0;
+	    parser->bytes_in_buffer = 0;
+	    return FALSE;
+	}
+    }
+
+    memmove (parser->buffer + parser->bytes_in_buffer, data, length);
+    parser->bytes_in_buffer += length;
+    parser->buffer[parser->bytes_in_buffer] = 0;
+
+    bytes_parsed = resource_parse_lines (parser);
+
+    if (parser->bytes_in_buffer > bytes_parsed) {
+	memmove (parser->buffer, parser->buffer + bytes_parsed, parser->bytes_in_buffer - bytes_parsed);
+	parser->bytes_in_buffer -= bytes_parsed;
+    } else {
+	parser->bytes_in_buffer = 0;
+    }
+
+    return TRUE;
+}
+
+static void
+resource_parser_done (struct resource_parser *parser)
+{
+    if (parser->bytes_in_buffer > 0) {
+	parser->buffer[parser->bytes_in_buffer] = 0;
+	resource_parse_line (parser->buffer, parser->resources);
+    }
+
+    free (parser->buffer);
+}
+
+static void
+get_resources(xcb_connection_t *connection, xcb_screen_t *screen, cairo_xcb_resources_t *resources)
+{
+    xcb_get_property_cookie_t cookie;
+    xcb_get_property_reply_t *reply;
+    struct resource_parser parser;
+    int offset;
+    cairo_bool_t has_more_data;
+
+    resources->xft_antialias = TRUE;
+    resources->xft_lcdfilter = -1;
+    resources->xft_hinting = TRUE;
+    resources->xft_hintstyle = FC_HINT_FULL;
+    resources->xft_rgba = FC_RGBA_UNKNOWN;
+
+    resource_parser_init (&parser, resources);
+
+    offset = 0;
+    has_more_data = FALSE;
+    do {
+	cookie = xcb_get_property (connection, 0, screen->root, XCB_ATOM_RESOURCE_MANAGER, XCB_ATOM_STRING, offset, 1024);
+	reply = xcb_get_property_reply (connection, cookie, NULL);
+
+	if (reply) {
+	    if (reply->format == 8 && reply->type == XCB_ATOM_STRING) {
+		char *value = (char *) xcb_get_property_value (reply);
+		int length = xcb_get_property_value_length (reply);
+
+		offset += length / 4; /* X needs the offset in 'long' units */
+		has_more_data = reply->bytes_after > 0;
+
+		if (! resource_parser_update (&parser, value, length))
+		    has_more_data = FALSE; /* early exit on error */
+	    }
+
+	    free (reply);
+	}
+    } while (has_more_data);
+
+    resource_parser_done (&parser);
+}
+
+#if 0 && XCB_RENDER_MAJOR_VERSION > 99 && XCB_RENDER_MINOR_VERSION > 99
+static void
+get_rgba_from_render (xcb_connection_t *connection, xcb_screen_t *screen, cairo_xcb_resources_t *resources)
+{
+    /* this is a mock-up of what the function might look like,
+       xcb_render_query_sub_pixel is not actually implemented in XCB (yet) */
+
+    xcb_render_query_sub_pixel_order_cookie_t cookie;
+    xcb_render_query_sub_pixel_order_reply_t *reply;
+
+    cookie = xcb_render_query_sub_pixel (connection, screen);
+    reply = xcb_render_query_sub_pixel_reply (connection, cookie, NULL);
+
+    if (reply) {
+	switch (reply->sub_pixel_order) {
+	case XCB_RENDER_SUB_PIXEL_UNKNOWN:
+	    resources->xft_rgba = FC_RGBA_UNKNOWN;
+	    break;
+	case XCB_RENDER_SUB_PIXEL_HORIZONTAL_RGB:
+	    resources->xft_rgba = FC_RGBA_RGB;
+	    break;
+	case XCB_RENDER_SUB_PIXEL_HORIZONTAL_BGR:
+	    resources->xft_rgba = FC_RGBA_BGR;
+	    break;
+	case XCB_RENDER_SUB_PIXEL_VERTICAL_RGB:
+	    resources->xft_rgba = FC_RGBA_VRGB;
+	    break;
+	case XCB_RENDER_SUB_PIXEL_VERTICAL_BGR:
+	    resources->xft_rgba = FC_RGBA_VBGR;
+	    break;
+	case XCB_RENDER_SUB_PIXEL_NONE:
+	    resources->xft_rgba = FC_RGBA_NONE;
+	    break;
+	}
+
+	free(reply);
+    }
+}
+#endif
+
+void
+_cairo_xcb_resources_get (cairo_xcb_screen_t *screen, cairo_xcb_resources_t *resources)
+{
+    get_resources (screen->connection->xcb_connection, screen->xcb_screen, resources);
+
+#if 0 && XCB_RENDER_MAJOR_VERSION > 99 && XCB_RENDER_MINOR_VERSION > 99
+    if (resources->xft_rgba == FC_RGBA_UNKNOWN) {
+	get_rgba_from_render (screen->connection->xcb_connection, screen->xcb_screen, resources);
+    }
+#endif
+}
diff --git a/src/cairo-xcb-screen.c b/src/cairo-xcb-screen.c
index 2858d23..30295af 100644
--- a/src/cairo-xcb-screen.c
+++ b/src/cairo-xcb-screen.c
@@ -35,6 +35,96 @@
 #include "cairo-xcb-private.h"
 #include "cairo-list-inline.h"
 
+#include "cairo-fontconfig-private.h"
+
+static void
+_cairo_xcb_init_screen_font_options (cairo_xcb_screen_t *screen)
+{
+    cairo_xcb_resources_t res;
+    cairo_antialias_t antialias;
+    cairo_subpixel_order_t subpixel_order;
+    cairo_lcd_filter_t lcd_filter;
+    cairo_hint_style_t hint_style;
+
+    _cairo_xcb_resources_get (screen, &res);
+
+    /* the rest of the code in this function is copied from
+       _cairo_xlib_init_screen_font_options in cairo-xlib-screen.c */
+
+    if (res.xft_hinting) {
+	switch (res.xft_hintstyle) {
+	case FC_HINT_NONE:
+	    hint_style = CAIRO_HINT_STYLE_NONE;
+	    break;
+	case FC_HINT_SLIGHT:
+	    hint_style = CAIRO_HINT_STYLE_SLIGHT;
+	    break;
+	case FC_HINT_MEDIUM:
+	    hint_style = CAIRO_HINT_STYLE_MEDIUM;
+	    break;
+	case FC_HINT_FULL:
+	    hint_style = CAIRO_HINT_STYLE_FULL;
+	    break;
+	default:
+	    hint_style = CAIRO_HINT_STYLE_DEFAULT;
+	}
+    } else {
+	hint_style = CAIRO_HINT_STYLE_NONE;
+    }
+
+    switch (res.xft_rgba) {
+    case FC_RGBA_RGB:
+	subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
+	break;
+    case FC_RGBA_BGR:
+	subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
+	break;
+    case FC_RGBA_VRGB:
+	subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
+	break;
+    case FC_RGBA_VBGR:
+	subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
+	break;
+    case FC_RGBA_UNKNOWN:
+    case FC_RGBA_NONE:
+    default:
+	subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+    }
+
+    switch (res.xft_lcdfilter) {
+    case FC_LCD_NONE:
+	lcd_filter = CAIRO_LCD_FILTER_NONE;
+	break;
+    case FC_LCD_DEFAULT:
+	lcd_filter = CAIRO_LCD_FILTER_FIR5;
+	break;
+    case FC_LCD_LIGHT:
+	lcd_filter = CAIRO_LCD_FILTER_FIR3;
+	break;
+    case FC_LCD_LEGACY:
+	lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
+	break;
+    default:
+	lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
+	break;
+    }
+
+    if (res.xft_antialias) {
+	if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
+	    antialias = CAIRO_ANTIALIAS_GRAY;
+	else
+	    antialias = CAIRO_ANTIALIAS_SUBPIXEL;
+    } else {
+	antialias = CAIRO_ANTIALIAS_NONE;
+    }
+
+    cairo_font_options_set_hint_style (&screen->font_options, hint_style);
+    cairo_font_options_set_antialias (&screen->font_options, antialias);
+    cairo_font_options_set_subpixel_order (&screen->font_options, subpixel_order);
+    _cairo_font_options_set_lcd_filter (&screen->font_options, lcd_filter);
+    cairo_font_options_set_hint_metrics (&screen->font_options, CAIRO_HINT_METRICS_ON);
+}
+
 struct pattern_cache_entry {
     cairo_cache_entry_t key;
     cairo_xcb_screen_t *screen;
@@ -362,3 +452,21 @@ _cairo_xcb_screen_lookup_radial_picture (cairo_xcb_screen_t *screen,
 
     return picture;
 }
+
+cairo_font_options_t *
+_cairo_xcb_screen_get_font_options (cairo_xcb_screen_t *screen)
+{
+    if (! screen->has_font_options) {
+	_cairo_font_options_init_default (&screen->font_options);
+	_cairo_font_options_set_round_glyph_positions (&screen->font_options, CAIRO_ROUND_GLYPH_POS_ON);
+
+	if (! _cairo_xcb_connection_acquire (screen->connection)) {
+	    _cairo_xcb_init_screen_font_options (screen);
+	    _cairo_xcb_connection_release (screen->connection);
+	}
+
+	screen->has_font_options = TRUE;
+    }
+
+    return &screen->font_options;
+}
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 02e7a19..d7e0d73 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -530,9 +530,9 @@ static void
 _cairo_xcb_surface_get_font_options (void *abstract_surface,
 				     cairo_font_options_t *options)
 {
-    /* XXX  copy from xlib */
-    _cairo_font_options_init_default (options);
-    _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
+    cairo_xcb_surface_t *surface = abstract_surface;
+
+    *options = *_cairo_xcb_screen_get_font_options (surface->screen);
 }
 
 static cairo_status_t


More information about the cairo-commit mailing list