mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-24 16:00:11 +01:00
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@oxygene.sk> Reviewed-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
e77d0a5611
commit
e691d242d5
5 changed files with 435 additions and 3 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
304
src/cairo-xcb-resources.c
Normal file
304
src/cairo-xcb-resources.c
Normal file
|
|
@ -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@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
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue