diff options
author | John Mark Bell <jmb@netsurf-browser.org> | 2009-06-19 10:44:47 +0000 |
---|---|---|
committer | John Mark Bell <jmb@netsurf-browser.org> | 2009-06-19 10:44:47 +0000 |
commit | cc4d98bb8bf6177c523e0fbbc0b8385891528198 (patch) | |
tree | 0822ad09ef5d6a2759d718019529d24beeb8f4b1 | |
parent | 2a4f3b8fc1e09fa982d3fc9cf97451b5ad1ca04d (diff) | |
download | libcss-cc4d98bb8bf6177c523e0fbbc0b8385891528198.tar.gz libcss-cc4d98bb8bf6177c523e0fbbc0b8385891528198.tar.bz2 |
Parse background shorthand property
svn path=/trunk/libcss/; revision=7874
-rw-r--r-- | src/parse/properties/background.c | 229 | ||||
-rw-r--r-- | src/parse/properties/properties.c | 1 | ||||
-rw-r--r-- | src/parse/properties/properties.h | 3 | ||||
-rw-r--r-- | src/parse/propstrings.c | 1 | ||||
-rw-r--r-- | src/parse/propstrings.h | 15 |
5 files changed, 242 insertions, 7 deletions
diff --git a/src/parse/properties/background.c b/src/parse/properties/background.c index d769d73..0afef30 100644 --- a/src/parse/properties/background.c +++ b/src/parse/properties/background.c @@ -14,6 +14,235 @@ #include "parse/properties/utils.h" /** + * Parse background + * + * \param c Parsing context + * \param vector Vector of tokens to process + * \param ctx Pointer to vector iteration context + * \param result Pointer to location to receive resulting style + * \return CSS_OK on success, + * CSS_NOMEM on memory exhaustion, + * CSS_INVALID if the input is not a valid background-attachment + * + * Post condition: \a *ctx is updated with the next token to process + * If the input is invalid, then \a *ctx remains unchanged. + */ +css_error parse_background(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + int orig_ctx = *ctx; + int prev_ctx; + const css_token *token; + css_style *attachment = NULL; + css_style *color = NULL; + css_style *image = NULL; + css_style *position = NULL; + css_style *repeat = NULL; + css_style *ret = NULL; + uint32_t required_size; + css_error error; + + /* Firstly, handle inherit */ + token = parserutils_vector_peek(vector, *ctx); + if (token != NULL && token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[INHERIT]) { + uint32_t *bytecode; + + error = css_stylesheet_style_create(c->sheet, + 5 * sizeof(uint32_t), &ret); + if (error != CSS_OK) { + *ctx = orig_ctx; + return error; + } + + bytecode = (uint32_t *) ret->bytecode; + + *(bytecode++) = buildOPV(CSS_PROP_BACKGROUND_ATTACHMENT, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_BACKGROUND_COLOR, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_BACKGROUND_IMAGE, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_BACKGROUND_POSITION, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_BACKGROUND_REPEAT, + FLAG_INHERIT, 0); + + parserutils_vector_iterate(vector, ctx); + + *result = ret; + + return CSS_OK; + } else if (token == NULL) { + /* No tokens -- clearly garbage */ + *ctx = orig_ctx; + return CSS_INVALID; + } + + /* Attempt to parse the various longhand properties */ + do { + prev_ctx = *ctx; + error = CSS_OK; + + /* Try each property parser in turn, but only if we + * haven't already got a value for this property. + * To achieve this, we end up with a bunch of empty + * if/else statements. Perhaps there's a clearer way + * of expressing this. */ + if (attachment == NULL && + (error = parse_background_attachment(c, vector, + ctx, &attachment)) == CSS_OK) { + } else if (color == NULL && + (error = parse_background_color(c, vector, ctx, + &color)) == CSS_OK) { + } else if (image == NULL && + (error = parse_background_image(c, vector, ctx, + &image)) == CSS_OK) { + } else if (position == NULL && + (error = parse_background_position(c, vector, + ctx, &position)) == CSS_OK) { + } else if (repeat == NULL && + (error = parse_background_repeat(c, vector, + ctx, &repeat)) == CSS_OK) { + } + + if (error == CSS_OK) { + consumeWhitespace(vector, ctx); + + token = parserutils_vector_peek(vector, *ctx); + } else { + /* Forcibly cause loop to exit */ + token = NULL; + } + } while (*ctx != prev_ctx && token != NULL); + + /* Calculate the required size of the resultant style, + * defaulting the unspecified properties to their initial values */ + required_size = 0; + + if (attachment) + required_size += attachment->length; + else + required_size += sizeof(uint32_t); + + if (color) + required_size += color->length; + else + required_size += sizeof(uint32_t); + + if (image) + required_size += image->length; + else + required_size += sizeof(uint32_t); + + if (position) + required_size += position->length; + else + required_size += sizeof(uint32_t); /* Use top left, not 0% 0% */ + + if (repeat) + required_size += repeat->length; + else + required_size += sizeof(uint32_t); + + /* Create and populate it */ + error = css_stylesheet_style_create(c->sheet, required_size, &ret); + if (error != CSS_OK) + goto cleanup; + + required_size = 0; + + if (attachment) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + attachment->bytecode, attachment->length); + required_size += attachment->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_BACKGROUND_ATTACHMENT, + 0, BACKGROUND_ATTACHMENT_SCROLL); + required_size += sizeof(uint32_t); + } + + if (color) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + color->bytecode, color->length); + required_size += color->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_BACKGROUND_COLOR, + 0, BACKGROUND_COLOR_TRANSPARENT); + required_size += sizeof(uint32_t); + } + + if (image) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + image->bytecode, image->length); + required_size += image->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_BACKGROUND_IMAGE, + 0, BACKGROUND_IMAGE_NONE); + required_size += sizeof(uint32_t); + } + + if (position) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + position->bytecode, position->length); + required_size += position->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_BACKGROUND_POSITION, + 0, BACKGROUND_POSITION_HORZ_LEFT | + BACKGROUND_POSITION_VERT_TOP); + required_size += sizeof(uint32_t); + } + + if (repeat) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + repeat->bytecode, repeat->length); + required_size += repeat->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_BACKGROUND_REPEAT, + 0, BACKGROUND_REPEAT_REPEAT); + required_size += sizeof(uint32_t); + } + + assert(required_size == ret->length); + + /* Write the result */ + *result = ret; + /* Invalidate ret, so that cleanup doesn't destroy it */ + ret = NULL; + + /* Clean up after ourselves */ +cleanup: + if (attachment) + css_stylesheet_style_destroy(c->sheet, attachment); + if (color) + css_stylesheet_style_destroy(c->sheet, color); + if (image) + css_stylesheet_style_destroy(c->sheet, image); + if (position) + css_stylesheet_style_destroy(c->sheet, position); + if (repeat) + css_stylesheet_style_destroy(c->sheet, repeat); + if (ret) + css_stylesheet_style_destroy(c->sheet, ret); + + if (error != CSS_OK) + *ctx = orig_ctx; + + return error; +} + +/** * Parse background-attachment * * \param c Parsing context diff --git a/src/parse/properties/properties.c b/src/parse/properties/properties.c index a0edd29..8da730d 100644 --- a/src/parse/properties/properties.c +++ b/src/parse/properties/properties.c @@ -13,6 +13,7 @@ const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] = { parse_azimuth, + parse_background, parse_background_attachment, parse_background_color, parse_background_image, diff --git a/src/parse/properties/properties.h b/src/parse/properties/properties.h index 496d3dc..a41f2c9 100644 --- a/src/parse/properties/properties.h +++ b/src/parse/properties/properties.h @@ -25,6 +25,9 @@ extern const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP]; css_error parse_azimuth(css_language *c, const parserutils_vector *vector, int *ctx, css_style **result); +css_error parse_background(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); css_error parse_background_attachment(css_language *c, const parserutils_vector *vector, int *ctx, css_style **result); diff --git a/src/parse/propstrings.c b/src/parse/propstrings.c index 208b384..2098b60 100644 --- a/src/parse/propstrings.c +++ b/src/parse/propstrings.c @@ -43,6 +43,7 @@ const stringmap_entry stringmap[LAST_KNOWN] = { { "after", SLEN("after") }, { "azimuth", SLEN("azimuth") }, + { "background", SLEN("background") }, { "background-attachment", SLEN("background-attachment") }, { "background-color", SLEN("background-color") }, { "background-image", SLEN("background-image") }, diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h index 5931505..7f25c81 100644 --- a/src/parse/propstrings.h +++ b/src/parse/propstrings.h @@ -31,13 +31,14 @@ enum { /* Properties */ FIRST_PROP, - AZIMUTH = FIRST_PROP, BACKGROUND_ATTACHMENT, BACKGROUND_COLOR, - BACKGROUND_IMAGE, BACKGROUND_POSITION, BACKGROUND_REPEAT, - BORDER_BOTTOM_COLOR, BORDER_BOTTOM_STYLE, BORDER_BOTTOM_WIDTH, - BORDER_COLLAPSE, BORDER_LEFT_COLOR, BORDER_LEFT_STYLE, - BORDER_LEFT_WIDTH, BORDER_RIGHT_COLOR, BORDER_RIGHT_STYLE, - BORDER_RIGHT_WIDTH, BORDER_SPACING, BORDER_TOP_COLOR, BORDER_TOP_STYLE, - BORDER_TOP_WIDTH, BOTTOM, CAPTION_SIDE, CLEAR, CLIP, COLOR, CONTENT, + AZIMUTH = FIRST_PROP, BACKGROUND, BACKGROUND_ATTACHMENT, + BACKGROUND_COLOR, BACKGROUND_IMAGE, BACKGROUND_POSITION, + BACKGROUND_REPEAT, BORDER_BOTTOM_COLOR, BORDER_BOTTOM_STYLE, + BORDER_BOTTOM_WIDTH, BORDER_COLLAPSE, BORDER_LEFT_COLOR, + BORDER_LEFT_STYLE, BORDER_LEFT_WIDTH, BORDER_RIGHT_COLOR, + BORDER_RIGHT_STYLE, BORDER_RIGHT_WIDTH, BORDER_SPACING, + BORDER_TOP_COLOR, BORDER_TOP_STYLE, BORDER_TOP_WIDTH, BOTTOM, + CAPTION_SIDE, CLEAR, CLIP, COLOR, CONTENT, COUNTER_INCREMENT, COUNTER_RESET, CUE_AFTER, CUE_BEFORE, CURSOR, DIRECTION, DISPLAY, ELEVATION, EMPTY_CELLS, FLOAT, FONT_FAMILY, FONT_SIZE, FONT_STYLE, FONT_VARIANT, FONT_WEIGHT, HEIGHT, LEFT, |