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/css.c | 55 +++++++++++- css/css.h | 38 +++++++- css/css_enums | 3 +- css/parser.y | 58 +++++++----- css/ruleset.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 403 insertions(+), 28 deletions(-) (limited to 'css') diff --git a/css/css.c b/css/css.c index ebf446dba..c42ad3d21 100644 --- a/css/css.c +++ b/css/css.c @@ -103,6 +103,11 @@ static void css_dump_selector(const struct css_selector *r); * spec. */ const struct css_style css_base_style = { 0xffffff, + CSS_BACKGROUND_ATTACHMENT_SCROLL, + { CSS_BACKGROUND_IMAGE_NONE, 0 }, + { { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } }, + { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } } }, + CSS_BACKGROUND_REPEAT_REPEAT, { { 0x000000, { CSS_BORDER_WIDTH_LENGTH, { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE }, { 0x000000, { CSS_BORDER_WIDTH_LENGTH, @@ -143,6 +148,11 @@ const struct css_style css_base_style = { /** Style with no values set. */ const struct css_style css_empty_style = { CSS_COLOR_INHERIT, + CSS_BACKGROUND_ATTACHMENT_INHERIT, + { CSS_BACKGROUND_IMAGE_INHERIT, 0 }, + { { CSS_BACKGROUND_POSITION_INHERIT, { 0.0 } }, + { CSS_BACKGROUND_POSITION_INHERIT, { 0.0 } } }, + CSS_BACKGROUND_REPEAT_INHERIT, { { CSS_COLOR_INHERIT, { CSS_BORDER_WIDTH_INHERIT, { 0, CSS_UNIT_PX } }, CSS_BORDER_STYLE_INHERIT }, { CSS_COLOR_INHERIT, { CSS_BORDER_WIDTH_INHERIT, @@ -184,6 +194,11 @@ const struct css_style css_empty_style = { * and the 'Initial value' otherwise. */ const struct css_style css_blank_style = { TRANSPARENT, + CSS_BACKGROUND_ATTACHMENT_SCROLL, + { CSS_BACKGROUND_IMAGE_NONE, 0 }, + { { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } }, + { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } } }, + CSS_BACKGROUND_REPEAT_REPEAT, { { 0x000000, { CSS_BORDER_WIDTH_LENGTH, { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE }, { 0x000000, { CSS_BORDER_WIDTH_LENGTH, @@ -332,8 +347,11 @@ void css_destroy(struct content *c) struct css_selector *r; for (i = 0; i != HASH_SIZE; i++) { - for (r = c->data.css.css->rule[i]; r != 0; r = r->next) + for (r = c->data.css.css->rule[i]; r != 0; r = r->next) { + if (r->style->background_image.uri != NULL) + free(r->style->background_image.uri); free(r->style); + } css_free_selector(c->data.css.css->rule[i]); } free(c->data.css.css); @@ -361,7 +379,8 @@ void css_destroy(struct content *c) * Used by the parser. */ -struct css_node * css_new_node(css_node_type type, +struct css_node * css_new_node(struct content *stylesheet, + css_node_type type, const char *data, unsigned int data_length) { struct css_node *node = malloc(sizeof *node); @@ -375,6 +394,7 @@ struct css_node * css_new_node(css_node_type type, node->comb = CSS_COMB_NONE; node->style = 0; node->specificity = 0; + node->stylesheet = stylesheet; return node; } @@ -976,7 +996,9 @@ void css_dump_style(const struct css_style * const style) if (style->z != css_empty_style.z) \ fprintf(stderr, s ": %s; ", n[style->z]); + DUMP_KEYWORD(background_attachment, "background-attachment", css_background_attachment_name); DUMP_COLOR(background_color, "background-color"); + DUMP_KEYWORD(background_repeat, "background-repeat", css_background_repeat_name); DUMP_KEYWORD(clear, "clear", css_clear_name); DUMP_COLOR(color, "color"); DUMP_KEYWORD(cursor, "cursor", css_cursor_name); @@ -1294,9 +1316,14 @@ void css_cascade(struct css_style * const style, style->text_decoration = apply->text_decoration; /* if (style->display == CSS_DISPLAY_INLINE && apply->display != CSS_DISPLAY_INLINE) style->text_decoration = CSS_TEXT_DECORATION_NONE;*/ - + if (apply->background_attachment != CSS_BACKGROUND_ATTACHMENT_INHERIT) + style->background_attachment = apply->background_attachment; if (apply->background_color != CSS_COLOR_INHERIT) style->background_color = apply->background_color; + if (apply->background_image.type != CSS_BACKGROUND_IMAGE_INHERIT) + style->background_image = apply->background_image; + if (apply->background_repeat != CSS_BACKGROUND_REPEAT_INHERIT) + style->background_repeat = apply->background_repeat; if (apply->clear != CSS_CLEAR_INHERIT) style->clear = apply->clear; if (apply->color != CSS_COLOR_INHERIT) @@ -1332,6 +1359,14 @@ void css_cascade(struct css_style * const style, if (apply->white_space != CSS_WHITE_SPACE_INHERIT) style->white_space = apply->white_space; + /* background-position */ + if (apply->background_position.horz.pos != CSS_BACKGROUND_POSITION_INHERIT) { + style->background_position.horz = apply->background_position.horz; + } + if (apply->background_position.vert.pos != CSS_BACKGROUND_POSITION_INHERIT) { + style->background_position.vert = apply->background_position.vert; + } + /* font-size */ f = apply->font_size.value.percent / 100; switch (apply->font_size.size) { @@ -1402,8 +1437,14 @@ void css_merge(struct css_style * const style, { unsigned int i; + if (apply->background_attachment != CSS_BACKGROUND_ATTACHMENT_INHERIT) + style->background_attachment = apply->background_attachment; if (apply->background_color != CSS_COLOR_INHERIT) style->background_color = apply->background_color; + if (apply->background_image.type != CSS_BACKGROUND_IMAGE_INHERIT) + style->background_image = apply->background_image; + if (apply->background_repeat != CSS_BACKGROUND_REPEAT_INHERIT) + style->background_repeat = apply->background_repeat; if (apply->clear != CSS_CLEAR_INHERIT) style->clear = apply->clear; if (apply->color != CSS_COLOR_INHERIT) @@ -1443,6 +1484,14 @@ void css_merge(struct css_style * const style, if (apply->white_space != CSS_WHITE_SPACE_INHERIT) style->white_space = apply->white_space; + /* background-position */ + if (apply->background_position.horz.pos != CSS_BACKGROUND_POSITION_INHERIT) { + style->background_position.horz = apply->background_position.horz; + } + if (apply->background_position.vert.pos != CSS_BACKGROUND_POSITION_INHERIT) { + style->background_position.vert = apply->background_position.vert; + } + for (i = 0; i != 4; i++) { if (apply->border[i].color != CSS_COLOR_INHERIT) style->border[i].color = apply->border[i].color; diff --git a/css/css.h b/css/css.h index 14c53a065..d80df9333 100644 --- a/css/css.h +++ b/css/css.h @@ -53,10 +53,44 @@ typedef enum { CSS_TEXT_DECORATION_UNKNOWN = 0x1000 } css_text_decoration; +typedef enum { + CSS_BACKGROUND_POSITION_LENGTH, + CSS_BACKGROUND_POSITION_PERCENT, + CSS_BACKGROUND_POSITION_INHERIT +} css_background_position; + /** Representation of a complete CSS 2 style. */ struct css_style { colour background_color; + css_background_attachment background_attachment; + + struct { + enum { CSS_BACKGROUND_IMAGE_NONE, + CSS_BACKGROUND_IMAGE_INHERIT, + CSS_BACKGROUND_IMAGE_URI } type; + char *uri; + } background_image; + + struct { + struct { + css_background_position pos; + union { + float percent; + struct css_length length; + } value; + } horz; + struct { + css_background_position pos; + union { + float percent; + struct css_length length; + } value; + } vert; + } background_position; + + css_background_repeat background_repeat; + struct { colour color; struct { @@ -246,6 +280,7 @@ struct css_node { css_combinator comb; struct css_style *style; unsigned long specificity; + struct content *stylesheet; }; @@ -282,7 +317,8 @@ void css_destroy(struct content *c); #ifdef CSS_INTERNALS -struct css_node * css_new_node(css_node_type type, +struct css_node * css_new_node(struct content *stylesheet, + css_node_type type, const char *data, unsigned int data_length); void css_free_node(struct css_node *node); struct css_selector * css_new_selector(css_selector_type type, diff --git a/css/css_enums b/css/css_enums index 2cccda18a..9df8c81aa 100644 --- a/css/css_enums +++ b/css/css_enums @@ -1,7 +1,6 @@ css_unit em ex px in cm mm pt pc css_background_attachment inherit fixed scroll -css_background_position inherit top center bottom left right length percent -css_background_repeat inherit repeat repeat_x repeat_y no_repeat +css_background_repeat inherit repeat repeat-x repeat-y no-repeat css_border_style inherit none hidden dotted dashed solid double groove ridge inset outset css_clear inherit none both left right css_cursor inherit auto crosshair default pointer move e-resize ne-resize nw-resize n-resize se-resize sw-resize s-resize w-resize text wait help diff --git a/css/parser.y b/css/parser.y index fc7a56289..b0f0aeba3 100644 --- a/css/parser.y +++ b/css/parser.y @@ -211,7 +211,8 @@ declaration_list(A) ::= declaration(B) SEMI declaration_list(C). { if (B) { B->next = C; A = B; } else { A = C; } } declaration(A) ::= property(B) COLON value(C). - { if (C && (A = css_new_node(CSS_NODE_DECLARATION, + { if (C && (A = css_new_node(param->stylesheet, + CSS_NODE_DECLARATION, B.text, B.length))) A->value = C; else { @@ -245,58 +246,71 @@ any_list_1(A) ::= any(B) any_list(C). { if (B) { B->next = C; A = B; } else { css_free_node(B); css_free_node(C); A = 0; } } any(A) ::= IDENT(B). - { A = css_new_node(CSS_NODE_IDENT, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_IDENT, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= NUMBER(B). - { A = css_new_node(CSS_NODE_NUMBER, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_NUMBER, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= PERCENTAGE(B). - { A = css_new_node(CSS_NODE_PERCENTAGE, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_PERCENTAGE, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= DIMENSION(B). - { A = css_new_node(CSS_NODE_DIMENSION, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_DIMENSION, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= STRING(B). - { A = css_new_node(CSS_NODE_STRING, B.text + 1, B.length - 2); + { A = css_new_node(param->stylesheet, CSS_NODE_STRING, + B.text + 1, B.length - 2); if (!A) param->memory_error = true; } any(A) ::= DELIM(B). - { A = css_new_node(CSS_NODE_DELIM, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_DELIM, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= URI(B). - { A = css_new_node(CSS_NODE_URI, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_URI, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= HASH(B). - { A = css_new_node(CSS_NODE_HASH, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_HASH, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= UNICODE_RANGE(B). - { A = css_new_node(CSS_NODE_UNICODE_RANGE, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_UNICODE_RANGE, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= INCLUDES. - { A = css_new_node(CSS_NODE_INCLUDES, 0, 0); + { A = css_new_node(param->stylesheet, CSS_NODE_INCLUDES, + 0, 0); if (!A) param->memory_error = true; } any(A) ::= FUNCTION(B). - { A = css_new_node(CSS_NODE_FUNCTION, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_FUNCTION, + B.text, B.length); if (!A) param->memory_error = true; } any(A) ::= DASHMATCH. - { A = css_new_node(CSS_NODE_DASHMATCH, 0, 0); + { A = css_new_node(param->stylesheet, CSS_NODE_DASHMATCH, + 0, 0); if (!A) param->memory_error = true; } any(A) ::= COLON. - { A = css_new_node(CSS_NODE_COLON, 0, 0); + { A = css_new_node(param->stylesheet, CSS_NODE_COLON, 0, 0); if (!A) param->memory_error = true; } any(A) ::= COMMA. - { A = css_new_node(CSS_NODE_COMMA, 0, 0); + { A = css_new_node(param->stylesheet, CSS_NODE_COMMA, 0, 0); if (!A) param->memory_error = true; } any(A) ::= DOT. - { A = css_new_node(CSS_NODE_DOT, 0, 0); + { A = css_new_node(param->stylesheet, CSS_NODE_DOT, 0, 0); if (!A) param->memory_error = true; } any(A) ::= PLUS. - { A = css_new_node(CSS_NODE_PLUS, 0, 0); + { A = css_new_node(param->stylesheet, CSS_NODE_PLUS, 0, 0); if (!A) param->memory_error = true; } any(A) ::= GT. - { A = css_new_node(CSS_NODE_GT, 0, 0); + { A = css_new_node(param->stylesheet, CSS_NODE_GT, 0, 0); if (!A) param->memory_error = true; } any(A) ::= LPAREN any_list(B) RPAREN. - { if ((A = css_new_node(CSS_NODE_PAREN, 0, 0))) + { if ((A = css_new_node(param->stylesheet, CSS_NODE_PAREN, + 0, 0))) A->value = B; else { param->memory_error = true; @@ -304,7 +318,8 @@ any(A) ::= LPAREN any_list(B) RPAREN. A = 0; } } any(A) ::= LBRAC any_list(B) RBRAC. - { if ((A = css_new_node(CSS_NODE_BRAC, 0, 0))) + { if ((A = css_new_node(param->stylesheet, CSS_NODE_BRAC, + 0, 0))) A->value = B; else { param->memory_error = true; @@ -312,7 +327,8 @@ any(A) ::= LBRAC any_list(B) RBRAC. A = 0; } } any(A) ::= ASTERISK(B). - { A = css_new_node(CSS_NODE_DELIM, B.text, B.length); + { A = css_new_node(param->stylesheet, CSS_NODE_DELIM, + B.text, B.length); if (!A) param->memory_error = true; } 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