[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:
parent
9edb2fb92c
commit
ff74a126f7
25
css/css.h
25
css/css.h
|
@ -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);
|
||||
|
|
40
css/parser.y
40
css/parser.y
|
@ -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) ::= .
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);*/
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue