summaryrefslogtreecommitdiff
path: root/css
diff options
context:
space:
mode:
Diffstat (limited to 'css')
-rw-r--r--css/css.c55
-rw-r--r--css/css.h38
-rw-r--r--css/css_enums3
-rw-r--r--css/parser.y58
-rw-r--r--css/ruleset.c277
5 files changed, 403 insertions, 28 deletions
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)
{