From 779d92c2fb107df7cf2fcb2a3b214f4d7ed7945e Mon Sep 17 00:00:00 2001 From: Robert Staudinger Date: Tue, 2 Jun 2009 00:09:11 +0200 Subject: [node] Cache values queried from the node implementation. Node name, class, etc. are kept in the node instance to avoid having to query for them repeatedly. --- ccss/ccss-node-priv.h | 43 +++++++++- ccss/ccss-node.c | 191 ++++++++++++++++++++++++++++++++++++++++++--- ccss/ccss-node.h | 15 +++- ccss/ccss-selector-group.c | 30 +++---- ccss/ccss-selector-group.h | 2 +- ccss/ccss-selector.c | 32 +++----- ccss/ccss-selector.h | 2 +- ccss/ccss-stylesheet.c | 33 +++----- ccss/ccss-stylesheet.h | 2 +- configure.in | 4 +- examples/example-2.c | 2 +- 11 files changed, 278 insertions(+), 78 deletions(-) diff --git a/ccss/ccss-node-priv.h b/ccss/ccss-node-priv.h index d136b5c..4727d97 100644 --- a/ccss/ccss-node-priv.h +++ b/ccss/ccss-node-priv.h @@ -23,14 +23,53 @@ #define CCSS_NODE_PRIV_H #include +#include #include #include CCSS_BEGIN_DECLS bool -ccss_node_is_a (ccss_node_t const *self, - char const *type_name); +ccss_node_is_a (ccss_node_t *self, + char const *type_name); + +ccss_node_t * +ccss_node_get_container (ccss_node_t *self); + +ccss_node_t * +ccss_node_get_base_style (ccss_node_t *self); + +char const * +ccss_node_get_type (ccss_node_t *self); + +ptrdiff_t +ccss_node_get_instance (ccss_node_t *self); + +char const * +ccss_node_get_id (ccss_node_t *self); + +char const * +ccss_node_get_class (ccss_node_t *self); + +char const * +ccss_node_get_pseudo_class (ccss_node_t *self); + +char * +ccss_node_get_attribute (ccss_node_t const *self, + char const *name); + +char const * +ccss_node_get_style (ccss_node_t *self); + +bool +ccss_node_get_viewport (ccss_node_t const *self, + uint32_t *x, + uint32_t *y, + uint32_t *width, + uint32_t *height); + +void +ccss_node_release (ccss_node_t *self); CCSS_END_DECLS diff --git a/ccss/ccss-node.c b/ccss/ccss-node.c index fbd4df8..a30780d 100644 --- a/ccss/ccss-node.c +++ b/ccss/ccss-node.c @@ -25,25 +25,25 @@ #include "config.h" static bool -is_a (ccss_node_t const *self, +is_a (ccss_node_t *self, char const *type_name) { return FALSE; } -static ccss_node_t * +static ccss_node_t * get_container (ccss_node_t const *self) { return NULL; } -static ccss_node_t * +static ccss_node_t * get_base_style (ccss_node_t const *self) { return NULL; } -static char const * +static char const * get_type (ccss_node_t const *self) { return NULL; @@ -55,32 +55,32 @@ get_instance (ccss_node_t const *self) return 0; } -static char const * +static char const * get_id (ccss_node_t const *self) { return NULL; } -static char const * +static char const * get_class (ccss_node_t const *self) { return NULL; } -static char const * +static char const * get_pseudo_class (ccss_node_t const *self) { return NULL; } -static char * +static char * get_attribute (ccss_node_t const *self, char const *name) { return NULL; } -static char const * +static char const * get_style (ccss_node_t const *self) { return NULL; @@ -137,6 +137,8 @@ ccss_node_init (ccss_node_t *self, g_return_if_fail (self && node_class); + memset (self, 0, sizeof (*self)); + /* Initialize the node class. * FIXME: run only once per node class? */ default_vtable = (node_f const *) &_default_node_class; @@ -157,18 +159,181 @@ ccss_node_init (ccss_node_t *self, * implemented `get_type' is used as a fallback. **/ bool -ccss_node_is_a (ccss_node_t const *self, - char const *type_name) +ccss_node_is_a (ccss_node_t *self, + char const *type_name) { char const *node_type_name; + g_return_val_if_fail (self, FALSE); + g_return_val_if_fail (self->node_class, FALSE); + g_return_val_if_fail (type_name, FALSE); + if (self->node_class->is_a != is_a) { return self->node_class->is_a (self, type_name); } else { - node_type_name = self->node_class->get_type (self); + node_type_name = ccss_node_get_type (self); return node_type_name ? - 0 == strcmp (type_name, node_type_name) : + 0 == g_strcmp0 (type_name, node_type_name) : false; } } +ccss_node_t * +ccss_node_get_container (ccss_node_t *self) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_container, NULL); + + return self->node_class->get_container (self); + +/* We might cache this too in the future. + if (NULL == self->container) + self->container = self->node_class->get_container (self); + + return self->container; +*/ +} + +ccss_node_t * +ccss_node_get_base_style (ccss_node_t *self) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_base_style, NULL); + + return self->node_class->get_base_style (self); + +/* We might cache this too in the future. + if (NULL == self->base_style) + self->base_style = self->node_class->get_base_style (self); + + return self->base_style; +*/ +} + +char const * +ccss_node_get_type (ccss_node_t *self) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_type, NULL); + +return self->node_class->get_type (self); + + if (NULL == self->type_name) + self->type_name = self->node_class->get_type (self); + + return self->type_name; +} + +ptrdiff_t +ccss_node_get_instance (ccss_node_t *self) +{ + g_return_val_if_fail (self, 0); + g_return_val_if_fail (self->node_class, 0); + g_return_val_if_fail (self->node_class->get_instance, 0); + +return self->node_class->get_instance (self); + + if (0 == self->instance) + self->instance = self->node_class->get_instance (self); + + return self->instance; +} + +char const * +ccss_node_get_id (ccss_node_t *self) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_id, NULL); + +return self->node_class->get_id (self); + + if (NULL == self->id) + self->id = self->node_class->get_id (self); + + return self->id; +} + +char const * +ccss_node_get_class (ccss_node_t *self) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_class, NULL); + +return self->node_class->get_class (self); + + if (NULL == self->css_class) + self->css_class = self->node_class->get_class (self); + + return self->css_class; +} + +char const * +ccss_node_get_pseudo_class (ccss_node_t *self) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_pseudo_class, NULL); + +return self->node_class->get_pseudo_class (self); + + if (NULL == self->pseudo_class) + self->pseudo_class = self->node_class->get_pseudo_class (self); + + return self->pseudo_class; +} + +char * +ccss_node_get_attribute (ccss_node_t const *self, + char const *name) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_attribute, NULL); + + return self->node_class->get_attribute (self, name); +} + +char const * +ccss_node_get_style (ccss_node_t *self) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_style, NULL); + +return self->node_class->get_style (self); + + if (NULL == self->inline_style) + self->inline_style = self->node_class->get_style (self); + + return self->inline_style; +} + +bool +ccss_node_get_viewport (ccss_node_t const *self, + uint32_t *x, + uint32_t *y, + uint32_t *width, + uint32_t *height) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (self->node_class, NULL); + g_return_val_if_fail (self->node_class->get_viewport, NULL); + + return self->node_class->get_viewport (self, x, y, width, height); +} + +void +ccss_node_release (ccss_node_t *self) +{ + g_return_if_fail (self); + g_return_if_fail (self->node_class); + g_return_if_fail (self->node_class->release); + + self->node_class->release (self); +} + diff --git a/ccss/ccss-node.h b/ccss/ccss-node.h index 46b2de0..c692a06 100644 --- a/ccss/ccss-node.h +++ b/ccss/ccss-node.h @@ -40,8 +40,8 @@ typedef struct ccss_node_ ccss_node_t; * * Returns: %TRUE if matches. **/ -typedef bool (*ccss_node_is_a_f) (ccss_node_t const *self, - char const *type_name); +typedef bool (*ccss_node_is_a_f) (ccss_node_t *self, + char const *type_name); /** * ccss_node_get_container_f: @@ -212,6 +212,17 @@ typedef struct { struct ccss_node_ { /*< private >*/ ccss_node_class_t const *node_class; + +/* We might cache those too in the future. + ccss_node_t *container; + ccss_node_t *base_style; +*/ + ptrdiff_t instance; + char const *id; + char const *type_name; + char const *css_class; + char const *pseudo_class; + char const *inline_style; }; void diff --git a/ccss/ccss-selector-group.c b/ccss/ccss-selector-group.c index 31da670..ebd2fed 100644 --- a/ccss/ccss-selector-group.c +++ b/ccss/ccss-selector-group.c @@ -37,7 +37,7 @@ struct ccss_selector_group_ { static int compare (size_t key1, - size_t key2, + size_t key2, void *data) { return key1 - key2; @@ -74,8 +74,8 @@ ccss_selector_group_create (void) ccss_selector_group_t *self; self = g_new0 (ccss_selector_group_t, 1); - self->sets = g_tree_new_full ((GCompareDataFunc) compare, NULL, NULL, - (GDestroyNotify) free_set); + self->sets = g_tree_new_full ((GCompareDataFunc) compare, NULL, NULL, + (GDestroyNotify) free_set); self->n_selectors = 0; self->min_specificity_e = CCSS_SELECTOR_MAX_SPECIFICITY; @@ -86,7 +86,7 @@ ccss_selector_group_create (void) /** * ccss_selector_group_destroy: * @self: a #ccss_selector_group_t. - * + * * Free the selector group and all associated resources. **/ void @@ -102,8 +102,8 @@ ccss_selector_group_destroy (ccss_selector_group_t *self) * Takes ownership of the selector. */ void -ccss_selector_group_add_selector (ccss_selector_group_t *self, - ccss_selector_t *selector) +ccss_selector_group_add_selector (ccss_selector_group_t *self, + ccss_selector_t *selector) { ccss_selector_set_t *set; size_t specificity; @@ -127,8 +127,8 @@ calculate_min_specificity_e (ccss_selector_group_t *group, { unsigned int specificity_e; - /* The tree is walked in order, so we remember how many - * specificities `e' will be required to insert the merged selectors at + /* The tree is walked in order, so we remember how many + * specificities `e' will be required to insert the merged selectors at * the right place. `- 1' because "group->min_specificity_e" already has * the next free value. */ g_assert (((signed) group->min_specificity_e - (signed) n_specificities - 1) >= 0); @@ -175,7 +175,7 @@ ccss_selector_group_merge_as_base (ccss_selector_group_t *self, g_assert (self && group); info.self = self; - info.specificity_e = calculate_min_specificity_e (self, + info.specificity_e = calculate_min_specificity_e (self, self->n_selectors); g_tree_foreach (group->sets, (GTraverseFunc) traverse_merge, &info); @@ -208,7 +208,7 @@ ccss_selector_group_clear_dangling_selectors (ccss_selector_group_t *self) } typedef struct { - ccss_node_t const *node; + ccss_node_t *node; ccss_selector_group_t *result_group; bool as_base; unsigned int specificity_e; @@ -246,8 +246,8 @@ traverse_query (size_t specificity, } bool -ccss_selector_group_query (ccss_selector_group_t const *self, - ccss_node_t const *node, +ccss_selector_group_query (ccss_selector_group_t const *self, + ccss_node_t *node, bool as_base, ccss_selector_group_t *result_group) { @@ -306,7 +306,7 @@ traverse_apply (size_t specificity, } } else { - info->ret |= ccss_selector_apply (selector, + info->ret |= ccss_selector_apply (selector, info->node, info->style); } @@ -324,7 +324,7 @@ traverse_apply (size_t specificity, * Apply the styling information held by #self to #style. **/ bool -ccss_selector_group_apply (ccss_selector_group_t const *self, +ccss_selector_group_apply (ccss_selector_group_t const *self, ccss_node_t const *node, ccss_style_t *style) { @@ -353,7 +353,7 @@ ccss_selector_group_apply (ccss_selector_group_t const *self, * Returns: %TRUE if applicable style information available. **/ bool -ccss_selector_group_apply_type (ccss_selector_group_t const *self, +ccss_selector_group_apply_type (ccss_selector_group_t const *self, char const *type_name, ccss_style_t *style) { diff --git a/ccss/ccss-selector-group.h b/ccss/ccss-selector-group.h index fad0913..def0f72 100644 --- a/ccss/ccss-selector-group.h +++ b/ccss/ccss-selector-group.h @@ -65,7 +65,7 @@ ccss_selector_group_clear_dangling_selectors (ccss_selector_group_t *self); bool ccss_selector_group_query (ccss_selector_group_t const *self, - ccss_node_t const *node, + ccss_node_t *node, bool as_base, ccss_selector_group_t *result_group); diff --git a/ccss/ccss-selector.c b/ccss/ccss-selector.c index 7554059..afb1533 100644 --- a/ccss/ccss-selector.c +++ b/ccss/ccss-selector.c @@ -848,21 +848,18 @@ ccss_selector_get_specificity_values (ccss_selector_t const *self, static bool match_antecessor_r (ccss_selector_t const *self, - ccss_node_t const *node) + ccss_node_t *node) { - ccss_node_class_t const *node_class; ccss_node_t *container; bool is_matching; - node_class = node->node_class; - - container = node_class->get_container (node); + container = ccss_node_get_container (node); if (container) { is_matching = ccss_selector_query (self, container); if (!is_matching) { is_matching = match_antecessor_r (self, container); } - node_class->release (container); + ccss_node_release (container); } else { is_matching = false; } @@ -872,9 +869,8 @@ match_antecessor_r (ccss_selector_t const *self, bool ccss_selector_query (ccss_selector_t const *self, - ccss_node_t const *node) + ccss_node_t *node) { - ccss_node_class_t const *node_class; char const *name; char *value; ptrdiff_t instance; @@ -882,8 +878,6 @@ ccss_selector_query (ccss_selector_t const *self, g_return_val_if_fail (self && node, false); - node_class = node->node_class; - is_matching = false; switch (self->modality) { case CCSS_SELECTOR_MODALITY_UNIVERSAL: @@ -900,18 +894,18 @@ ccss_selector_query (ccss_selector_t const *self, is_matching = true; break; case CCSS_SELECTOR_MODALITY_CLASS: - name = node_class->get_class (node); + name = ccss_node_get_class (node); is_matching = !g_strcmp0 (name, ((ccss_class_selector_t *) self)->class_name); break; case CCSS_SELECTOR_MODALITY_ID: - name = node_class->get_id (node); + name = ccss_node_get_id (node); is_matching = !g_strcmp0 (name, ((ccss_id_selector_t *) self)->id); break; case CCSS_SELECTOR_MODALITY_ATTRIBUTE: name = ((ccss_attribute_selector_t *) self)->name; - value = node_class->get_attribute (node, name); + value = ccss_node_get_attribute (node, name); switch (((ccss_attribute_selector_t *) self)->match) { case CCSS_ATTRIBUTE_SELECTOR_MATCH_EXISTS: is_matching = value ? true : false; @@ -924,12 +918,12 @@ ccss_selector_query (ccss_selector_t const *self, g_free (value), value = NULL; break; case CCSS_SELECTOR_MODALITY_PSEUDO_CLASS: - name = node_class->get_pseudo_class (node); + name = ccss_node_get_pseudo_class (node); is_matching = !g_strcmp0 (name, ((ccss_pseudo_class_selector_t *) self)->pseudo_class); break; case CCSS_SELECTOR_MODALITY_INSTANCE: - instance = node_class->get_instance (node); + instance = ccss_node_get_instance (node); is_matching = (instance == ((ccss_instance_selector_t *) self)->instance); break; @@ -950,11 +944,11 @@ ccss_selector_query (ccss_selector_t const *self, /* match container */ if (self->container) { ccss_node_t *container; - container = node_class->get_container (node); + container = ccss_node_get_container (node); is_matching = false; if (container) { is_matching = ccss_selector_query (self->container, container); - node_class->release (container); + ccss_node_release (container); } if (!is_matching) { return false; @@ -977,7 +971,6 @@ ccss_selector_apply (ccss_selector_t const *self, ccss_node_t const *node, ccss_style_t *style) { - ccss_node_class_t const *node_class; GHashTableIter iter; gpointer key; gpointer value; @@ -998,8 +991,7 @@ ccss_selector_apply (ccss_selector_t const *self, /* Requiring a node instance here would make the type-based API impossible. */ if (node) { /* Update viewport (for things like fixed background-images). */ - node_class = node->node_class; - ret = node_class->get_viewport (node, &x, &y, &width, &height); + ret = ccss_node_get_viewport (node, &x, &y, &width, &height); if (ret) { style->viewport_x = x; style->viewport_y = y; diff --git a/ccss/ccss-selector.h b/ccss/ccss-selector.h index 60b2d96..ef82376 100644 --- a/ccss/ccss-selector.h +++ b/ccss/ccss-selector.h @@ -115,7 +115,7 @@ void ccss_selector_get_specificity_values (ccss_selector_t const *self, bool ccss_selector_query (ccss_selector_t const *self, - ccss_node_t const *node); + ccss_node_t *node); bool ccss_selector_apply (ccss_selector_t const *self, diff --git a/ccss/ccss-stylesheet.c b/ccss/ccss-stylesheet.c index cd7112c..50cf37a 100644 --- a/ccss/ccss-stylesheet.c +++ b/ccss/ccss-stylesheet.c @@ -23,7 +23,7 @@ #include #include "ccss-block-priv.h" #include "ccss-grammar-priv.h" -#include "ccss-node.h" +#include "ccss-node-priv.h" #include "ccss-selector-group.h" #include "ccss-selector.h" #include "ccss-style-priv.h" @@ -236,23 +236,20 @@ bail: */ static bool query_type_r (ccss_stylesheet_t const *self, - ccss_node_t const *node, - ccss_node_t const *iter, + ccss_node_t *node, + ccss_node_t *iter, bool as_base, ccss_selector_group_t *result_group) { - ccss_node_class_t const *node_class; ccss_selector_group_t *group; char const *type_name; bool ret; - node_class = node->node_class; - if (!iter) { iter = node; } - type_name = node_class->get_type (iter); + type_name = ccss_node_get_type (iter); ret = false; if (type_name) { @@ -265,10 +262,10 @@ query_type_r (ccss_stylesheet_t const *self, } /* Try to match base types. */ - base = node_class->get_base_style (iter); + base = ccss_node_get_base_style (iter); if (base) { ret |= query_type_r (self, node, base, true, result_group); - node_class->release (base); + ccss_node_release (base); } } else { g_warning ("No type name"); @@ -282,10 +279,9 @@ query_type_r (ccss_stylesheet_t const *self, */ static bool query_node (ccss_stylesheet_t const *self, - ccss_node_t const *node, + ccss_node_t *node, ccss_style_t *style) { - ccss_node_class_t const *node_class; ccss_selector_group_t const *universal_group; ccss_selector_group_t *result_group; char const *inline_css; @@ -308,11 +304,10 @@ query_node (ccss_stylesheet_t const *self, ret |= query_type_r (self, node, node, false, result_group); /* Handle inline styling. */ - node_class = node->node_class; - inline_css = node_class->get_style (node); + inline_css = ccss_node_get_style (node); if (inline_css) { ptrdiff_t instance; - instance = node_class->get_instance (node); + instance = ccss_node_get_instance (node); if (instance == 0) { g_warning ("Inline CSS `%s' but instance == 0\n", inline_css); } else { @@ -402,11 +397,10 @@ inherit_container_style (ccss_style_t const *container_style, **/ static bool query_container_r (ccss_stylesheet_t const *self, - ccss_node_t const *node, + ccss_node_t *node, GHashTable *inherit, ccss_style_t *style) { - ccss_node_class_t const *node_class; ccss_node_t *container; ccss_style_t *container_style; bool ret; @@ -414,8 +408,7 @@ query_container_r (ccss_stylesheet_t const *self, g_return_val_if_fail (style && node, false); /* Actually inherit. */ - node_class = node->node_class; - container = node_class->get_container (node); + container = ccss_node_get_container (node); if (!container) return false; @@ -435,7 +428,7 @@ query_container_r (ccss_stylesheet_t const *self, query_container_r (self, container, inherit, style); } - node_class->release (container), container = NULL; + ccss_node_release (container), container = NULL; /* Return true if some styling has been found, not necessarily all * properties resolved. */ @@ -454,7 +447,7 @@ query_container_r (ccss_stylesheet_t const *self, **/ ccss_style_t * ccss_stylesheet_query (ccss_stylesheet_t *self, - ccss_node_t const *node) + ccss_node_t *node) { GHashTable *inherit; GHashTableIter iter; diff --git a/ccss/ccss-stylesheet.h b/ccss/ccss-stylesheet.h index 03cc177..8a6ccde 100644 --- a/ccss/ccss-stylesheet.h +++ b/ccss/ccss-stylesheet.h @@ -70,7 +70,7 @@ ccss_stylesheet_query_type (ccss_stylesheet_t *self, ccss_style_t * ccss_stylesheet_query (ccss_stylesheet_t *self, - ccss_node_t const *node); + ccss_node_t *node); void ccss_stylesheet_invalidate_node (ccss_stylesheet_t const *self, diff --git a/configure.in b/configure.in index 15535d5..7f92f60 100644 --- a/configure.in +++ b/configure.in @@ -7,8 +7,8 @@ AC_PREREQ(2.54) m4_define([ccss_version_major], [0]) -m4_define([ccss_version_minor], [2]) -m4_define([ccss_version_micro], [2]) +m4_define([ccss_version_minor], [3]) +m4_define([ccss_version_micro], [0]) ### For the release: #m4_define([ccss_version_extra], []) ### On trunk: diff --git a/examples/example-2.c b/examples/example-2.c index 4673269..716ce60 100644 --- a/examples/example-2.c +++ b/examples/example-2.c @@ -88,7 +88,7 @@ main (int argc, node.instance = 0xdeadbeef; node.inline_css = "background-color: yellow"; - style = ccss_stylesheet_query (stylesheet, (ccss_node_t const *) &node); + style = ccss_stylesheet_query (stylesheet, &node.parent); g_assert (style); #ifdef CCSS_DEBUG -- cgit v1.2.3