From 78594f3f60a2ce28f1d6ee95676bfa10492320fe Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Wed, 9 Jun 2004 19:55:06 +0000 Subject: [project @ 2004-06-09 19:55:06 by jmb] Implement background-image, background-repeat, background-position and background-attachment CSS properties. background-attachment and background-position need more work. Some redraw issues remain. svn path=/import/netsurf/; revision=938 --- css/ruleset.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 276 insertions(+), 1 deletion(-) (limited to 'css/ruleset.c') diff --git a/css/ruleset.c b/css/ruleset.c index e2e0d03bd..345b86225 100644 --- a/css/ruleset.c +++ b/css/ruleset.c @@ -23,6 +23,7 @@ #include "netsurf/content/content.h" #include "netsurf/desktop/options.h" #include "netsurf/utils/log.h" +#include "netsurf/utils/url.h" #include "netsurf/utils/utils.h" @@ -33,7 +34,11 @@ static int parse_length(struct css_length * const length, const struct css_node * const v, bool non_negative); static colour parse_colour(const struct css_node * const v); static void parse_background(struct css_style * const s, const struct css_node * v); +static void parse_background_attachment(struct css_style * const s, const struct css_node * const v); static void parse_background_color(struct css_style * const s, const struct css_node * const v); +static void parse_background_image(struct css_style * const s, const struct css_node * const v); +static void parse_background_position(struct css_style * const s, const struct css_node * const v); +static void parse_background_repeat(struct css_style * const s, const struct css_node * const v); static void parse_border(struct css_style * const s, const struct css_node * v); static void parse_border_bottom(struct css_style * const s, const struct css_node * v); static void parse_border_bottom_color(struct css_style * const s, const struct css_node * v); @@ -102,7 +107,7 @@ static css_text_decoration css_text_decoration_parse(const char * const s, /** An entry in css_property_table. */ struct css_property_entry { - const char name[20]; + const char name[25]; void (*parse) (struct css_style * const s, const struct css_node * const v); }; @@ -110,7 +115,11 @@ struct css_property_entry { /** Table of property parsers. MUST be sorted by property name. */ static const struct css_property_entry css_property_table[] = { { "background", parse_background }, + { "background-attachment", parse_background_attachment }, { "background-color", parse_background_color }, + { "background-image", parse_background_image }, + { "background-position", parse_background_position }, + { "background-repeat", parse_background_repeat }, { "border", parse_border }, { "border-bottom", parse_border_bottom }, { "border-bottom-color", parse_border_bottom_color }, @@ -481,6 +490,16 @@ void parse_background(struct css_style * const s, const struct css_node * v) } } +void parse_background_attachment(struct css_style * const s, const struct css_node * const v) +{ + css_background_attachment z; + if (v->type != CSS_NODE_IDENT || v->next != 0) + return; + z = css_background_attachment_parse(v->data, v->data_length); + if (z != CSS_BACKGROUND_ATTACHMENT_UNKNOWN) + s->background_attachment = z; +} + void parse_background_color(struct css_style * const s, const struct css_node * const v) { colour c = parse_colour(v); @@ -488,6 +507,262 @@ void parse_background_color(struct css_style * const s, const struct css_node * s->background_color = c; } +void parse_background_image(struct css_style * const s, const struct css_node * const v) +{ + bool string = false; + const char *u; + char *t, *url; + s->background_image.uri = 0; + + switch (v->type) { + case CSS_NODE_URI: + for (u = v->data + 4; + *u == ' ' || *u == '\t' || *u == '\r' || + *u == '\n' || *u == '\f'; + u++) + ; + if (*u == '\'' || *u == '"') { + string = true; + u++; + } + url = strndup(u, v->data_length - (u - v->data)); + if (!url) { + return; + } + for (t = url + strlen(url) - 2; + *t == ' ' || *t == '\t' || *t == '\r' || + *t == '\n' || *t == '\f'; + t--) + ; + if (string) + *t = 0; + else + *(t + 1) = 0; + + s->background_image.uri = url_join(url, v->stylesheet->url); + free(url); + if (!s->background_image.uri) return; + s->background_image.type = CSS_BACKGROUND_IMAGE_URI; + break; + case CSS_NODE_STRING: + url = strndup(v->data, v->data_length); + if (!url) + return; + + s->background_image.uri = url_join(url, v->stylesheet->url); + free(url); + if (!s->background_image.uri) return; + s->background_image.type = CSS_BACKGROUND_IMAGE_URI; + break; + case CSS_NODE_IDENT: + if (v->data_length == 7 && strncasecmp(v->data, "inherit", 7) == 0) + s->background_image.type = CSS_BACKGROUND_IMAGE_INHERIT; + else if (v->data_length == 4 && strncasecmp(v->data, "none", 4) == 0) + s->background_image.type = CSS_BACKGROUND_IMAGE_NONE; + break; + default: + break; + } +} + +void parse_background_position(struct css_style * const s, const struct css_node * v) +{ + struct css_node *w = v->next; + + if (!w) { /* only one value specified */ + if (v->type == CSS_NODE_IDENT) { + if (v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 50.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 0.0; + } + else if (v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 0.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + else if (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 50.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + else if (v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 100.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + else if (v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 50.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 100.0; + } + } + else if (v->type == CSS_NODE_PERCENTAGE) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = atof(v->data); + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + else if (v->type == CSS_NODE_DIMENSION) { + + if (parse_length(&s->background_position.horz.value.length, v, false) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_LENGTH; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + } + } + + /* two values specified */ + if (v->type == CSS_NODE_IDENT && w->type == CSS_NODE_IDENT) { + /* both keywords */ + if ((v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0 && w->data_length == 4 && strncasecmp(w->data, "left", 4) == 0) || + (v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0 && w->data_length == 3 && strncasecmp(w->data, "top", 3) == 0)) { + /* top left / left top */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 0.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 0.0; + } + else if ((v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) || + (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 3 && strncasecmp(w->data, "top", 3) == 0)) { + /* top center / center top */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 50.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 0.0; + } + else if ((v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0 && w->data_length == 5 && strncasecmp(w->data, "right", 5) == 0) || + (v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0 && w->data_length == 3 && strncasecmp(w->data, "top", 3) == 0)) { + /* top right / right top */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 100.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 0.0; + } + else if ((v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) || + (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 4 && strncasecmp(w->data, "left", 4) == 0)) { + /* left center / center left */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 0.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + else if (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) { + /* center center */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 50.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + else if ((v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) || + (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 5 && strncasecmp(w->data, "right", 5) == 0)) { + /* right center / center right */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 100.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + else if ((v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0 && w->data_length == 4 && strncasecmp(w->data, "left", 4) == 0) || + (v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0 && w->data_length == 6 && strncasecmp(w->data, "bottom", 6) == 0)) { + /* bottom left / left bottom */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 0.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 100.0; + } + else if ((v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) || + (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 6 && strncasecmp(w->data, "bottom", 6) == 0)) { + /* bottom center / center bottom */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 50.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 100.0; + } + else if ((v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0 && w->data_length == 5 && strncasecmp(w->data, "right", 5) == 0) || + (v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0 && w->data_length == 6 && strncasecmp(w->data, "bottom", 6) == 0)) { + /* bottom right / right bottom */ + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 100.0; + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 100.0; + } + } + else { + switch (v->type) { /* horizontal value */ + case CSS_NODE_IDENT: + if (v->data_length == 7 && strncasecmp(v->data, "inherit", 7) == 0) + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_INHERIT; + else if (v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 0.0; + } + else if (v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 100.0; + } + else if (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0) { + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = 50.0; + } + break; + case CSS_NODE_PERCENTAGE: + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.horz.value.percent = atof(v->data); + break; + case CSS_NODE_DIMENSION: + if (parse_length(&s->background_position.horz.value.length, v, false) == 0) + s->background_position.horz.pos = CSS_BACKGROUND_POSITION_LENGTH; + break; + default: + break; + } + switch (w->type) { /* vertical value */ + case CSS_NODE_IDENT: + if (v->data_length == 7 && strncasecmp(v->data, "inherit", 7) == 0) + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_INHERIT; + else if (v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0) { + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 0.0; + } + else if (v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0) { + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 100.0; + } + else if (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0) { + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = 50.0; + } + break; + case CSS_NODE_PERCENTAGE: + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT; + s->background_position.vert.value.percent = atof(v->data); + break; + case CSS_NODE_DIMENSION: + if (parse_length(&s->background_position.vert.value.length, v, false) == 0) + s->background_position.vert.pos = CSS_BACKGROUND_POSITION_LENGTH; + break; + default: + break; + } + } +} + +void parse_background_repeat(struct css_style * const s, const struct css_node * const v) +{ + css_background_repeat z; + if (v->type != CSS_NODE_IDENT || v->next != 0) + return; + z = css_background_repeat_parse(v->data, v->data_length); + if (z != CSS_BACKGROUND_REPEAT_UNKNOWN) + s->background_repeat = z; +} + void parse_border_width(struct css_style * const s, const struct css_node * const v) { -- cgit v1.2.3