Port st-theme-context.[ch] to eek-theme-context.[ch].

This commit is contained in:
Daiki Ueno
2011-03-08 06:58:20 +09:00
parent 9be07710dd
commit baae80fa41
9 changed files with 883 additions and 21 deletions

View File

@ -47,7 +47,8 @@ libeek_private_headers = \
$(srcdir)/eek-special-keysym-entries.h \
$(srcdir)/eek-unicode-keysym-entries.h \
$(srcdir)/eek-xkeysym-keysym-entries.h \
$(srcdir)/eek-marshalers.h \
$(srcdir)/eek-marshalers.h \
$(srcdir)/eek-theme-context.h \
$(srcdir)/eek-theme-node.h
libeek_sources = \
@ -66,6 +67,7 @@ libeek_sources = \
$(srcdir)/eek-renderer.c \
$(srcdir)/eek-keyboard-drawing.c \
$(srcdir)/eek-theme.c \
$(srcdir)/eek-theme-context.c \
$(srcdir)/eek-theme-node.c
libeek_keysym_sources = \

View File

@ -1256,6 +1256,7 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
}
struct _CreateThemeNodeData {
EekThemeContext *context;
EekThemeNode *parent;
EekRenderer *renderer;
};
@ -1263,7 +1264,7 @@ typedef struct _CreateThemeNodeData CreateThemeNodeData;
void
create_theme_node_key_callback (EekElement *element,
gpointer user_data)
gpointer user_data)
{
CreateThemeNodeData *data = user_data;
EekRendererPrivate *priv;
@ -1271,7 +1272,8 @@ create_theme_node_key_callback (EekElement *element,
priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
theme_node = eek_theme_node_new (data->parent,
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_KEY,
eek_element_get_name (element),
@ -1283,7 +1285,8 @@ create_theme_node_key_callback (EekElement *element,
theme_node,
(GDestroyNotify)g_object_unref);
theme_node = eek_theme_node_new (data->parent,
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_KEY,
eek_element_get_name (element),
@ -1306,7 +1309,8 @@ create_theme_node_section_callback (EekElement *element,
priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
theme_node = eek_theme_node_new (data->parent,
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_SECTION,
eek_element_get_name (element),
@ -1331,6 +1335,7 @@ eek_renderer_set_theme (EekRenderer *renderer,
EekTheme *theme)
{
EekRendererPrivate *priv;
EekThemeContext *theme_context;
EekThemeNode *theme_node;
CreateThemeNodeData data;
@ -1344,7 +1349,9 @@ eek_renderer_set_theme (EekRenderer *renderer,
g_object_unref (priv->theme);
priv->theme = g_object_ref (theme);
theme_node = eek_theme_node_new (NULL,
theme_context = eek_theme_context_new ();
theme_node = eek_theme_node_new (theme_context,
NULL,
priv->theme,
EEK_TYPE_KEYBOARD,
"keyboard",
@ -1356,6 +1363,7 @@ eek_renderer_set_theme (EekRenderer *renderer,
theme_node,
(GDestroyNotify)g_object_unref);
data.context = theme_context;
data.parent = theme_node;
data.renderer = renderer;
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),

View File

@ -26,6 +26,7 @@
#include "eek-keysym.h"
#include "eek-types.h"
#include "eek-theme.h"
#include "eek-theme-context.h"
G_BEGIN_DECLS

288
eek/eek-theme-context.c Normal file
View File

@ -0,0 +1,288 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/*
* eek-theme-context.c: holds global information about a tree of styled objects
*
* Copyright 2009, 2010 Red Hat, Inc.
* Copyright 2009 Florian Müllner
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-theme.h"
#include "eek-theme-context.h"
struct _EekThemeContext {
GObject parent;
double resolution;
PangoFontDescription *font;
EekThemeNode *root_node;
EekTheme *theme;
};
struct _EekThemeContextClass {
GObjectClass parent_class;
};
#define DEFAULT_RESOLUTION 96.
#define DEFAULT_FONT "sans-serif 10"
enum
{
CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekThemeContext, eek_theme_context, G_TYPE_OBJECT)
static void
eek_theme_context_finalize (GObject *object)
{
EekThemeContext *context = EEK_THEME_CONTEXT (object);
if (context->root_node)
g_object_unref (context->root_node);
if (context->theme)
g_object_unref (context->theme);
pango_font_description_free (context->font);
G_OBJECT_CLASS (eek_theme_context_parent_class)->finalize (object);
}
static void
eek_theme_context_class_init (EekThemeContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = eek_theme_context_finalize;
signals[CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, /* no default handler slot */
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
eek_theme_context_init (EekThemeContext *context)
{
context->resolution = DEFAULT_RESOLUTION;
context->font = pango_font_description_from_string (DEFAULT_FONT);
}
/**
* eek_theme_context_new:
*
* Create a new theme context.
*/
EekThemeContext *
eek_theme_context_new (void)
{
EekThemeContext *context;
context = g_object_new (EEK_TYPE_THEME_CONTEXT, NULL);
return context;
}
static void
eek_theme_context_changed (EekThemeContext *context)
{
EekThemeNode *old_root = context->root_node;
context->root_node = NULL;
g_signal_emit (context, signals[CHANGED], 0);
if (old_root)
g_object_unref (old_root);
}
/**
* eek_theme_context_set_theme:
* @context: a #EekThemeContext
*
* Sets the default set of theme stylesheets for the context. This theme will
* be used for the root node and for nodes descending from it, unless some other
* style is explicitely specified.
*/
void
eek_theme_context_set_theme (EekThemeContext *context,
EekTheme *theme)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
g_return_if_fail (theme == NULL || EEK_IS_THEME (theme));
if (context->theme != theme)
{
if (context->theme)
g_object_unref (context->theme);
context->theme = theme;
if (context->theme)
g_object_ref (context->theme);
eek_theme_context_changed (context);
}
}
/**
* eek_theme_context_get_theme:
* @context: a #EekThemeContext
*
* Gets the default theme for the context. See eek_theme_context_set_theme()
*
* Return value: (transfer none): the default theme for the context
*/
EekTheme *
eek_theme_context_get_theme (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
return context->theme;
}
/**
* eek_theme_context_set_resolution:
* @context: a #EekThemeContext
* @resolution: resolution of the context (number of pixels in an "inch")
*
* Sets the resolution of the theme context. This is the scale factor
* used to convert between points and the length units pt, in, and cm.
* This does not necessarily need to correspond to the actual number
* resolution of the device. A value of 72. means that points and
* pixels are identical. The default value is 96.
*/
void
eek_theme_context_set_resolution (EekThemeContext *context,
double resolution)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
if (resolution == context->resolution)
return;
context->resolution = resolution;
eek_theme_context_changed (context);
}
/**
* eek_theme_context_set_default_resolution:
* @context: a #EekThemeContext
*
* Sets the resolution of the theme context to the default value of 96.
* See eek_theme_context_set_resolution().
*/
void
eek_theme_context_set_default_resolution (EekThemeContext *context)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
if (context->resolution == DEFAULT_RESOLUTION)
return;
context->resolution = DEFAULT_RESOLUTION;
eek_theme_context_changed (context);
}
/**
* eek_theme_context_get_resolution:
* @context: a #EekThemeContext
*
* Gets the current resolution of the theme context.
* See eek_theme_context_set_resolution().
*
* Return value: the resolution (in dots-per-"inch")
*/
double
eek_theme_context_get_resolution (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), DEFAULT_RESOLUTION);
return context->resolution;
}
/**
* eek_theme_context_set_font:
* @context: a #EekThemeContext
* @font: the default font for theme context
*
* Sets the default font for the theme context. This is the font that
* is inherited by the root node of the tree of theme nodes. If the
* font is not overriden, then this font will be used. If the font is
* partially modified (for example, with 'font-size: 110%', then that
* modification is based on this font.
*/
void
eek_theme_context_set_font (EekThemeContext *context,
const PangoFontDescription *font)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
g_return_if_fail (font != NULL);
if (context->font == font ||
pango_font_description_equal (context->font, font))
return;
pango_font_description_free (context->font);
context->font = pango_font_description_copy (font);
eek_theme_context_changed (context);
}
/**
* eek_theme_context_get_font:
* @context: a #EekThemeContext
*
* Gets the default font for the theme context. See eek_theme_context_set_font().
*
* Return value: the default font for the theme context.
*/
const PangoFontDescription *
eek_theme_context_get_font (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
return context->font;
}
/**
* eek_theme_context_get_root_node:
* @context: a #EekThemeContext
*
* Gets the root node of the tree of theme style nodes that associated with this
* context. For the node tree associated with a stage, this node represents
* styles applied to the stage itself.
*
* Return value: (transfer none): the root node of the context's style tree
*/
EekThemeNode *
eek_theme_context_get_root_node (EekThemeContext *context)
{
if (context->root_node == NULL)
context->root_node = eek_theme_node_new (context, NULL, context->theme,
G_TYPE_NONE, NULL, NULL, NULL, NULL);
return context->root_node;
}

78
eek/eek-theme-context.h Normal file
View File

@ -0,0 +1,78 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* eek-theme-context.c: holds global information about a tree of styled objects
*
* Copyright 2009, 2010 Red Hat, Inc.
* Copyright 2009 Florian Müllner
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EEK_THEME_CONTEXT_H__
#define __EEK_THEME_CONTEXT_H__
#include <pango/pango.h>
#include "eek-theme-node.h"
G_BEGIN_DECLS
/**
* SECTION:EekThemeContext
* @short_description: holds global information about a tree of styled objects
*
* #EekThemeContext is responsible for managing information global to
* a tree of styled objects, such as the set of stylesheets or the
* default font.
*/
typedef struct _EekThemeContextClass EekThemeContextClass;
#define EEK_TYPE_THEME_CONTEXT (eek_theme_context_get_type ())
#define EEK_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EEK_TYPE_THEME_CONTEXT, EekThemeContext))
#define EEK_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
#define EEK_IS_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EEK_TYPE_THEME_CONTEXT))
#define EEK_IS_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_CONTEXT))
#define EEK_THEME_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
GType eek_theme_context_get_type
(void) G_GNUC_CONST;
EekThemeContext *eek_theme_context_new
(void);
void eek_theme_context_set_theme
(EekThemeContext *context,
EekTheme *theme);
EekTheme * eek_theme_context_get_theme
(EekThemeContext *context);
void eek_theme_context_set_resolution
(EekThemeContext *context,
gdouble resolution);
void eek_theme_context_set_default_resolution
(EekThemeContext *context);
double eek_theme_context_get_resolution
(EekThemeContext *context);
void eek_theme_context_set_font
(EekThemeContext *context,
const PangoFontDescription *font);
const PangoFontDescription *eek_theme_context_get_font
(EekThemeContext *context);
EekThemeNode * eek_theme_context_get_root_node
(EekThemeContext *context);
G_END_DECLS
#endif /* __EEK_THEME_CONTEXT_H__ */

View File

@ -31,15 +31,19 @@
#include <string.h>
#include <libcroco/libcroco.h>
#include "eek-theme-context.h"
#include "eek-theme-node.h"
#include "eek-theme-private.h"
struct _EekThemeNode {
GObject parent;
EekThemeContext *context;
EekThemeNode *parent_node;
EekTheme *theme;
PangoFontDescription *font_desc;
EekGradientType background_gradient_type;
EekColor background_color;
@ -108,6 +112,12 @@ eek_theme_node_dispose (GObject *gobject)
{
EekThemeNode *node = EEK_THEME_NODE (gobject);
if (node->context)
{
g_object_unref (node->context);
node->context = NULL;
}
if (node->theme)
{
g_object_unref (node->theme);
@ -146,6 +156,12 @@ eek_theme_node_finalize (GObject *object)
cr_declaration_destroy (node->inline_properties);
}
if (node->font_desc)
{
pango_font_description_free (node->font_desc);
node->font_desc = NULL;
}
G_OBJECT_CLASS (eek_theme_node_parent_class)->finalize (object);
}
@ -171,20 +187,23 @@ eek_theme_node_finalize (GObject *object)
* Return value: (transfer full): the theme node
*/
EekThemeNode *
eek_theme_node_new (EekThemeNode *parent_node,
EekTheme *theme,
GType element_type,
const char *element_id,
const char *element_class,
const char *pseudo_class,
const char *inline_style)
eek_theme_node_new (EekThemeContext *context,
EekThemeNode *parent_node,
EekTheme *theme,
GType element_type,
const char *element_id,
const char *element_class,
const char *pseudo_class,
const char *inline_style)
{
EekThemeNode *node;
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
g_return_val_if_fail (parent_node == NULL || EEK_IS_THEME_NODE (parent_node), NULL);
node = g_object_new (EEK_TYPE_THEME_NODE, NULL);
node->context = g_object_ref (context);
if (parent_node != NULL)
node->parent_node = g_object_ref (parent_node);
else
@ -635,6 +654,15 @@ eek_theme_node_get_double (EekThemeNode *node,
}
}
static const PangoFontDescription *
get_parent_font (EekThemeNode *node)
{
if (node->parent_node)
return eek_theme_node_get_font (node->parent_node);
else
return eek_theme_context_get_font (node->context);
}
static GetFromTermResult
get_length_from_term (EekThemeNode *node,
CRTerm *term,
@ -750,16 +778,11 @@ get_length_from_term (EekThemeNode *node,
*length = num->val * multiplier;
break;
case POINTS:
#if 0
{
double resolution = eek_theme_context_get_resolution (node->context);
*length = num->val * multiplier * (resolution / 72.);
}
#else
*length = num->val * multiplier;
#endif
break;
#if 0
case FONT_RELATIVE:
{
const PangoFontDescription *desc;
@ -783,7 +806,7 @@ get_length_from_term (EekThemeNode *node,
}
}
break;
#endif
default:
g_assert_not_reached ();
}
@ -1392,3 +1415,455 @@ eek_theme_node_get_background_gradient (EekThemeNode *node,
*end = node->background_gradient_end;
}
}
static gboolean
font_family_from_terms (CRTerm *term,
char **family)
{
GString *family_string;
gboolean result = FALSE;
gboolean last_was_quoted = FALSE;
if (!term)
return FALSE;
family_string = g_string_new (NULL);
while (term)
{
if (term->type != TERM_STRING && term->type != TERM_IDENT)
{
goto out;
}
if (family_string->len > 0)
{
if (term->the_operator != COMMA && term->the_operator != NO_OP)
goto out;
/* Can concatenate two bare words, but not two quoted strings */
if ((term->the_operator == NO_OP && last_was_quoted) || term->type == TERM_STRING)
goto out;
if (term->the_operator == NO_OP)
g_string_append (family_string, " ");
else
g_string_append (family_string, ", ");
}
else
{
if (term->the_operator != NO_OP)
goto out;
}
g_string_append (family_string, term->content.str->stryng->str);
term = term->next;
}
result = TRUE;
out:
if (result)
{
*family = g_string_free (family_string, FALSE);
return TRUE;
}
else
{
*family = g_string_free (family_string, TRUE);
return FALSE;
}
}
/* In points */
static int font_sizes[] = {
6 * 1024, /* xx-small */
8 * 1024, /* x-small */
10 * 1024, /* small */
12 * 1024, /* medium */
16 * 1024, /* large */
20 * 1024, /* x-large */
24 * 1024, /* xx-large */
};
static gboolean
font_size_from_term (EekThemeNode *node,
CRTerm *term,
double *size)
{
if (term->type == TERM_IDENT)
{
double resolution = eek_theme_context_get_resolution (node->context);
/* We work in integers to avoid double comparisons when converting back
* from a size in pixels to a logical size.
*/
int size_points = (int)(0.5 + *size * (72. / resolution));
if (strcmp (term->content.str->stryng->str, "xx-small") == 0)
size_points = font_sizes[0];
else if (strcmp (term->content.str->stryng->str, "x-small") == 0)
size_points = font_sizes[1];
else if (strcmp (term->content.str->stryng->str, "small") == 0)
size_points = font_sizes[2];
else if (strcmp (term->content.str->stryng->str, "medium") == 0)
size_points = font_sizes[3];
else if (strcmp (term->content.str->stryng->str, "large") == 0)
size_points = font_sizes[4];
else if (strcmp (term->content.str->stryng->str, "x-large") == 0)
size_points = font_sizes[5];
else if (strcmp (term->content.str->stryng->str, "xx-large") == 0)
size_points = font_sizes[6];
else if (strcmp (term->content.str->stryng->str, "smaller") == 0)
{
/* Find the standard size equal to or smaller than the current size */
int i = 0;
while (i <= 6 && font_sizes[i] < size_points)
i++;
if (i > 6)
{
/* original size greater than any standard size */
size_points = (int)(0.5 + size_points / 1.2);
}
else
{
/* Go one smaller than that, if possible */
if (i > 0)
i--;
size_points = font_sizes[i];
}
}
else if (strcmp (term->content.str->stryng->str, "larger") == 0)
{
/* Find the standard size equal to or larger than the current size */
int i = 6;
while (i >= 0 && font_sizes[i] > size_points)
i--;
if (i < 0) /* original size smaller than any standard size */
i = 0;
/* Go one larger than that, if possible */
if (i < 6)
i++;
size_points = font_sizes[i];
}
else
{
return FALSE;
}
*size = size_points * (resolution / 72.);
return TRUE;
}
else if (term->type == TERM_NUMBER && term->content.num->type == NUM_PERCENTAGE)
{
*size *= term->content.num->val / 100.;
return TRUE;
}
else if (get_length_from_term (node, term, TRUE, size) == VALUE_FOUND)
{
/* Convert from pixels to Pango units */
*size *= 1024;
return TRUE;
}
return FALSE;
}
static gboolean
font_weight_from_term (CRTerm *term,
PangoWeight *weight,
gboolean *weight_absolute)
{
if (term->type == TERM_NUMBER)
{
int weight_int;
/* The spec only allows numeric weights from 100-900, though Pango
* will handle any number. We just let anything through.
*/
if (term->content.num->type != NUM_GENERIC)
return FALSE;
weight_int = (int)(0.5 + term->content.num->val);
*weight = weight_int;
*weight_absolute = TRUE;
}
else if (term->type == TERM_IDENT)
{
/* FIXME: handle INHERIT */
if (strcmp (term->content.str->stryng->str, "bold") == 0)
{
*weight = PANGO_WEIGHT_BOLD;
*weight_absolute = TRUE;
}
else if (strcmp (term->content.str->stryng->str, "normal") == 0)
{
*weight = PANGO_WEIGHT_NORMAL;
*weight_absolute = TRUE;
}
else if (strcmp (term->content.str->stryng->str, "bolder") == 0)
{
*weight = PANGO_WEIGHT_BOLD;
*weight_absolute = FALSE;
}
else if (strcmp (term->content.str->stryng->str, "lighter") == 0)
{
*weight = PANGO_WEIGHT_LIGHT;
*weight_absolute = FALSE;
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
return TRUE;
}
static gboolean
font_style_from_term (CRTerm *term,
PangoStyle *style)
{
if (term->type != TERM_IDENT)
return FALSE;
/* FIXME: handle INHERIT */
if (strcmp (term->content.str->stryng->str, "normal") == 0)
*style = PANGO_STYLE_NORMAL;
else if (strcmp (term->content.str->stryng->str, "oblique") == 0)
*style = PANGO_STYLE_OBLIQUE;
else if (strcmp (term->content.str->stryng->str, "italic") == 0)
*style = PANGO_STYLE_ITALIC;
else
return FALSE;
return TRUE;
}
static gboolean
font_variant_from_term (CRTerm *term,
PangoVariant *variant)
{
if (term->type != TERM_IDENT)
return FALSE;
/* FIXME: handle INHERIT */
if (strcmp (term->content.str->stryng->str, "normal") == 0)
*variant = PANGO_VARIANT_NORMAL;
else if (strcmp (term->content.str->stryng->str, "small-caps") == 0)
*variant = PANGO_VARIANT_SMALL_CAPS;
else
return FALSE;
return TRUE;
}
const PangoFontDescription *
eek_theme_node_get_font (EekThemeNode *node)
{
/* Initialized despite _set flags to suppress compiler warnings */
PangoStyle font_style = PANGO_STYLE_NORMAL;
gboolean font_style_set = FALSE;
PangoVariant variant = PANGO_VARIANT_NORMAL;
gboolean variant_set = FALSE;
PangoWeight weight = PANGO_WEIGHT_NORMAL;
gboolean weight_absolute = TRUE;
gboolean weight_set = FALSE;
double size = 0.;
gboolean size_set = FALSE;
char *family = NULL;
double parent_size;
int i;
if (node->font_desc)
return node->font_desc;
node->font_desc = pango_font_description_copy (get_parent_font (node));
parent_size = pango_font_description_get_size (node->font_desc);
if (!pango_font_description_get_size_is_absolute (node->font_desc))
{
double resolution = eek_theme_context_get_resolution (node->context);
parent_size *= (resolution / 72.);
}
ensure_properties (node);
for (i = 0; i < node->n_properties; i++)
{
CRDeclaration *decl = node->properties[i];
if (strcmp (decl->property->stryng->str, "font") == 0)
{
PangoStyle tmp_style = PANGO_STYLE_NORMAL;
PangoVariant tmp_variant = PANGO_VARIANT_NORMAL;
PangoWeight tmp_weight = PANGO_WEIGHT_NORMAL;
gboolean tmp_weight_absolute = TRUE;
double tmp_size;
CRTerm *term = decl->value;
/* A font specification starts with node/variant/weight
* in any order. Each is allowed to be specified only once,
* but we don't enforce that.
*/
for (; term; term = term->next)
{
if (font_style_from_term (term, &tmp_style))
continue;
if (font_variant_from_term (term, &tmp_variant))
continue;
if (font_weight_from_term (term, &tmp_weight, &tmp_weight_absolute))
continue;
break;
}
/* The size is mandatory */
if (term == NULL || term->type != TERM_NUMBER)
{
g_warning ("Size missing from font property");
continue;
}
tmp_size = parent_size;
if (!font_size_from_term (node, term, &tmp_size))
{
g_warning ("Couldn't parse size in font property");
continue;
}
term = term->next;
if (term != NULL && term->type && TERM_NUMBER && term->the_operator == DIVIDE)
{
/* Ignore line-height specification */
term = term->next;
}
/* the font family is mandatory - it is a comma-separated list of
* names.
*/
if (!font_family_from_terms (term, &family))
{
g_warning ("Couldn't parse family in font property");
continue;
}
font_style = tmp_style;
font_style_set = TRUE;
weight = tmp_weight;
weight_absolute = tmp_weight_absolute;
weight_set = TRUE;
variant = tmp_variant;
variant_set = TRUE;
size = tmp_size;
size_set = TRUE;
}
else if (strcmp (decl->property->stryng->str, "font-family") == 0)
{
if (!font_family_from_terms (decl->value, &family))
{
g_warning ("Couldn't parse family in font property");
continue;
}
}
else if (strcmp (decl->property->stryng->str, "font-weight") == 0)
{
if (decl->value == NULL || decl->value->next != NULL)
continue;
if (font_weight_from_term (decl->value, &weight, &weight_absolute))
weight_set = TRUE;
}
else if (strcmp (decl->property->stryng->str, "font-style") == 0)
{
if (decl->value == NULL || decl->value->next != NULL)
continue;
if (font_style_from_term (decl->value, &font_style))
font_style_set = TRUE;
}
else if (strcmp (decl->property->stryng->str, "font-variant") == 0)
{
if (decl->value == NULL || decl->value->next != NULL)
continue;
if (font_variant_from_term (decl->value, &variant))
variant_set = TRUE;
}
else if (strcmp (decl->property->stryng->str, "font-size") == 0)
{
gdouble tmp_size;
if (decl->value == NULL || decl->value->next != NULL)
continue;
tmp_size = parent_size;
if (font_size_from_term (node, decl->value, &tmp_size))
{
size = tmp_size;
size_set = TRUE;
}
}
}
if (family)
{
pango_font_description_set_family (node->font_desc, family);
g_free (family);
}
if (size_set)
pango_font_description_set_absolute_size (node->font_desc, size);
if (weight_set)
{
if (!weight_absolute)
{
/* bolder/lighter are supposed to switch between available styles, but with
* font substitution, that gets to be a pretty fuzzy concept. So we use
* a fixed step of 200. (The spec says 100, but that might not take us from
* normal to bold.
*/
PangoWeight old_weight = pango_font_description_get_weight (node->font_desc);
if (weight == PANGO_WEIGHT_BOLD)
weight = old_weight + 200;
else
weight = old_weight - 200;
if (weight < 100)
weight = 100;
if (weight > 900)
weight = 900;
}
pango_font_description_set_weight (node->font_desc, weight);
}
if (font_style_set)
pango_font_description_set_style (node->font_desc, font_style);
if (variant_set)
pango_font_description_set_variant (node->font_desc, variant);
return node->font_desc;
}

View File

@ -20,6 +20,7 @@
#ifndef __EEK_THEME_NODE_H__
#define __EEK_THEME_NODE_H__
#include <pango/pango.h>
#include "eek-types.h"
G_BEGIN_DECLS
@ -70,7 +71,8 @@ typedef struct _EekThemeNodePrivate EekThemeNodePrivate;
GType eek_theme_node_get_type
(void) G_GNUC_CONST;
EekThemeNode *eek_theme_node_new (EekThemeNode *parent_node,
EekThemeNode *eek_theme_node_new (EekThemeContext *context,
EekThemeNode *parent_node,
/* can be null */ EekTheme *theme,
/* can be null */ GType element_type,
const char *element_id,
@ -127,6 +129,13 @@ void eek_theme_node_get_border_color
EekSide side,
EekColor *color);
/* Font rule processing is pretty complicated, so we just hardcode it
* under the standard font/font-family/font-size/etc names. This means
* you can't have multiple separate styled fonts for a single item,
* but that should be OK.
*/
const PangoFontDescription *eek_theme_node_get_font (EekThemeNode *node);
G_END_DECLS
#endif /* __EEK_THEME_NODE_H__ */

View File

@ -4,7 +4,7 @@
#include <glib-object.h>
#include "eek-theme-node.h"
#include "eek-types.h"
G_BEGIN_DECLS

View File

@ -137,6 +137,7 @@ typedef struct _EekKeyboard EekKeyboard;
typedef struct _EekSymbol EekSymbol;
typedef struct _EekKeysym EekKeysym;
typedef struct _EekTheme EekTheme;
typedef struct _EekThemeContext EekThemeContext;
typedef struct _EekThemeNode EekThemeNode;
typedef struct _EekSymbolMatrix EekSymbolMatrix;