[project @ 2005-05-21 23:30:19 by bursa]

Improve selector specificity support by adding "working stylesheets" with pre-sorted lists of rules. This also simplifies css_get_style(). The stylesheet origin is now encoded in the specificity. Improve output of css_dump_style().

svn path=/import/netsurf/; revision=1729
This commit is contained in:
James Bursa 2005-05-21 23:30:19 +00:00
parent 9edb2fb92c
commit ff74a126f7
6 changed files with 861 additions and 695 deletions

1455
css/css.c

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,17 @@ typedef unsigned long colour; /* 0xbbggrr */
#define RIGHT 1
#define BOTTOM 2
#define LEFT 3
#define CSS_SPECIFICITY_UA 0x0000000
#define CSS_SPECIFICITY_USER 0x1000000
#define CSS_SPECIFICITY_AUTHOR 0x2000000
#define CSS_SPECIFICITY_ID 0x10000
#define CSS_SPECIFICITY_CLASS 0x100
#define CSS_SPECIFICITY_ATTR 0x100
#define CSS_SPECIFICITY_ELEMENT 0x1
struct css_working_stylesheet;
/** Representation of a CSS 2 length. */
struct css_length {
@ -461,12 +472,19 @@ struct css_style {
struct css_stylesheet;
typedef enum {
CSS_ORIGIN_AUTHOR,
CSS_ORIGIN_USER,
CSS_ORIGIN_UA
} css_origin;
/** Data specific to CONTENT_CSS. */
struct content_css_data {
struct css_stylesheet *css; /**< Opaque stylesheet data. */
unsigned int import_count; /**< Number of entries in import_url. */
char **import_url; /**< Imported stylesheet urls. */
struct content **import_content; /**< Imported stylesheet contents. */
css_origin origin; /**< Origin of stylesheet. */
};
@ -615,7 +633,12 @@ const char *css_parser_TokenName(int tokenType);
#endif
void css_get_style(struct content *c, xmlNode *n, struct css_style * style);
void css_set_origin(struct content *c, css_origin origin);
struct css_working_stylesheet *css_make_working_stylesheet(
struct content **stylesheet_content,
unsigned int stylesheet_count);
void css_get_style(struct css_working_stylesheet *working_stylesheet,
xmlNode *element, struct css_style *style);
struct css_style *css_duplicate_style(const struct css_style * const style);
void css_free_style(struct css_style *style);
void css_deep_free_content(struct css_content *content);

View File

@ -118,7 +118,7 @@ simple_selector(A) ::= element_name(B) detail_list(C).
simple_selector(A) ::= element_name(B).
{ if ((A = css_new_selector(CSS_SELECTOR_ELEMENT,
B.text, B.length)))
A->specificity = 1;
A->specificity = CSS_SPECIFICITY_ELEMENT;
else
param->memory_error = true;
}
@ -152,93 +152,93 @@ detail_list(A) ::= detail(B) detail_list(C).
detail(A) ::= HASH(B).
{ A = css_new_selector(CSS_SELECTOR_ID, B.text+1, B.length-1);
if (A) A->specificity = 0x10000;
if (A) A->specificity = CSS_SPECIFICITY_ID;
else param->memory_error = true; }
detail(A) ::= DOT IDENT(B).
{ A = css_new_selector(CSS_SELECTOR_CLASS, B.text, B.length);
if (A) A->specificity = 0x100;
if (A) A->specificity = CSS_SPECIFICITY_CLASS;
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB, B.text, B.length);
if (A) A->specificity = 0x100;
if (A) A->specificity = CSS_SPECIFICITY_ATTR;
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws EQUALS ws IDENT(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_EQ, B.text, B.length);
if (A) { A->data2 = C.text; A->data2_length = C.length;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws EQUALS ws STRING(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_EQ, B.text, B.length);
if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws INCLUDES ws IDENT(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_INC, B.text, B.length);
if (A) { A->data2 = C.text; A->data2_length = C.length;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws INCLUDES ws STRING(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_INC, B.text, B.length);
if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws DASHMATCH ws IDENT(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_DM, B.text, B.length);
if (A) { A->data2 = C.text; A->data2_length = C.length;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws DASHMATCH ws STRING(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_DM, B.text, B.length);
if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws PREFIX ws IDENT(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_PRE, B.text, B.length);
if (A) { A->data2 = C.text; A->data2_length = C.length;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws PREFIX ws STRING(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_PRE, B.text, B.length);
if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws SUFFIX ws IDENT(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_SUF, B.text, B.length);
if (A) { A->data2 = C.text; A->data2_length = C.length;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws SUFFIX ws STRING(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_SUF, B.text, B.length);
if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws SUBSTR ws IDENT(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_SUB, B.text, B.length);
if (A) { A->data2 = C.text; A->data2_length = C.length;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= LBRAC ws IDENT(B) ws SUBSTR ws STRING(C) ws RBRAC.
{ A = css_new_selector(CSS_SELECTOR_ATTRIB_SUB, B.text, B.length);
if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2;
A->specificity = 0x100; }
A->specificity = CSS_SPECIFICITY_ATTR; }
else param->memory_error = true; }
detail(A) ::= COLON IDENT(B).
{ if (B.length == 4 && strncasecmp(B.text, "link", 4) == 0) {
A = css_new_selector(CSS_SELECTOR_ATTRIB, "href", 4);
if (A) A->specificity = 0x100;
if (A) A->specificity = CSS_SPECIFICITY_ATTR;
else param->memory_error = true;
} else {
A = css_new_selector(CSS_SELECTOR_PSEUDO, B.text, B.length);
if (A) A->specificity = 0x100;
if (A) A->specificity = CSS_SPECIFICITY_ATTR;
else param->memory_error = true;
} }
detail(A) ::= COLON FUNCTION(B) ws IDENT ws RPAREN.
{ A = css_new_selector(CSS_SELECTOR_PSEUDO, B.text, B.length);
if (A) A->specificity = 0x100;
if (A) A->specificity = CSS_SPECIFICITY_ATTR;
else param->memory_error = true; }
detail(A) ::= COLON FUNCTION(B) ws RPAREN.
{ A = css_new_selector(CSS_SELECTOR_PSEUDO, B.text, B.length);
if (A) A->specificity = 0x100;
if (A) A->specificity = CSS_SPECIFICITY_ATTR;
else param->memory_error = true; }
declaration_list(A) ::= .

View File

@ -456,8 +456,8 @@ bool box_construct_element(xmlNode *n, struct content *content,
xmlFree(s);
}
}
/* fetch any background image for this box */
if (style->background_image.type == CSS_BACKGROUND_IMAGE_URI) {
if (!html_fetch_object(content, style->background_image.uri,
@ -663,13 +663,7 @@ struct css_style * box_get_style(struct content *c,
style_new = talloc_memdup(c, &css_blank_style, sizeof *style_new);
if (!style_new)
return 0;
for (i = 0; i != stylesheet_count; i++) {
if (stylesheet[i]) {
assert(stylesheet[i]->type == CONTENT_CSS);
css_get_style(stylesheet[i], n, style_new);
}
}
css_get_style(c->data.html.working_stylesheet, n, style_new);
css_cascade(style, style_new);
/* style_new isn't needed past this point */
@ -701,7 +695,7 @@ struct css_style * box_get_style(struct content *c,
}
}
if (((s = (char *) xmlGetProp(n, (const xmlChar *) "bgcolor"))) &&
if (((s = (char *) xmlGetProp(n, (const xmlChar *) "bgcolor"))) &&
(style->background_color == TRANSPARENT)) {
unsigned int r, g, b;
if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)

View File

@ -628,6 +628,24 @@ bool html_find_stylesheets(struct content *c, xmlNode *head)
/* content_broadcast(c, CONTENT_MSG_STATUS, msg_data); */
/* } */
css_set_origin(c->data.html.stylesheet_content[STYLESHEET_BASE],
CSS_ORIGIN_UA);
if (c->data.html.stylesheet_content[STYLESHEET_ADBLOCK])
css_set_origin(c->data.html.stylesheet_content[
STYLESHEET_ADBLOCK], CSS_ORIGIN_UA);
if (c->data.html.stylesheet_content[STYLESHEET_STYLE])
css_set_origin(c->data.html.stylesheet_content[
STYLESHEET_STYLE], CSS_ORIGIN_AUTHOR);
for (i = STYLESHEET_START; i != c->data.html.stylesheet_count; i++)
css_set_origin(c->data.html.stylesheet_content[i],
CSS_ORIGIN_AUTHOR);
c->data.html.working_stylesheet = css_make_working_stylesheet(
c->data.html.stylesheet_content,
c->data.html.stylesheet_count);
if (!c->data.html.working_stylesheet)
return false;
return true;
}
@ -1137,6 +1155,8 @@ void html_destroy(struct content *c)
}
}
talloc_free(c->data.html.working_stylesheet);
/*if (c->data.html.style)
css_free_style(c->data.html.style);*/

View File

@ -69,6 +69,8 @@ struct content_html_data {
/** Stylesheets. Each may be 0. */
struct content **stylesheet_content;
struct css_style *style; /**< Base style. */
/** Working stylesheet. */
struct css_working_stylesheet *working_stylesheet;
/** Number of entries in object. */
unsigned int object_count;