From 2bc03416cd99fa9a4b8f8b7122ebe9907c21dc9b Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Thu, 25 Jun 2009 23:20:21 +0000 Subject: Padding shorthand property parser svn path=/trunk/libcss/; revision=7999 --- src/parse/properties/padding.c | 236 ++++++++++++++++++++++++++++++++++++++ src/parse/properties/properties.c | 1 + src/parse/properties/properties.h | 3 + src/parse/propstrings.c | 1 + src/parse/propstrings.h | 2 +- 5 files changed, 242 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/parse/properties/padding.c b/src/parse/properties/padding.c index 91dc264..d018609 100644 --- a/src/parse/properties/padding.c +++ b/src/parse/properties/padding.c @@ -5,6 +5,7 @@ * Copyright 2009 John-Mark Bell */ +#include #include #include "bytecode/bytecode.h" @@ -16,6 +17,241 @@ static css_error parse_padding_side(css_language *c, const parserutils_vector *vector, int *ctx, uint16_t op, css_style **result); +/** + * Parse padding shorthand + * + * \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 valid + * + * 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_padding(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 *top = NULL; + css_style *right = NULL; + css_style *bottom = NULL; + css_style *left = NULL; + css_style *ret = NULL; + uint32_t num_sides = 0; + 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, + 4 * sizeof(uint32_t), &ret); + if (error != CSS_OK) { + *ctx = orig_ctx; + return error; + } + + bytecode = (uint32_t *) ret->bytecode; + + *(bytecode++) = buildOPV(CSS_PROP_PADDING_TOP, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_PADDING_RIGHT, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_PADDING_BOTTOM, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_PADDING_LEFT, + 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 up to 4 widths */ + do { + prev_ctx = *ctx; + error = CSS_OK; + + if (top == NULL && + (error = parse_padding_side(c, vector, ctx, + CSS_PROP_PADDING_TOP, &top)) == CSS_OK) { + num_sides = 1; + } else if (right == NULL && + (error = parse_padding_side(c, vector, ctx, + CSS_PROP_PADDING_RIGHT, &right)) == CSS_OK) { + num_sides = 2; + } else if (bottom == NULL && + (error = parse_padding_side(c, vector, ctx, + CSS_PROP_PADDING_BOTTOM, &bottom)) == CSS_OK) { + num_sides = 3; + } else if (left == NULL && + (error = parse_padding_side(c, vector, ctx, + CSS_PROP_PADDING_LEFT, &left)) == CSS_OK) { + num_sides = 4; + } + + 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); + + if (num_sides == 0) { + error = CSS_INVALID; + goto cleanup; + } + + /* Calculate size of resultant style */ + if (num_sides == 1) { + required_size = 4 * top->length; + } else if (num_sides == 2) { + required_size = 2 * top->length + 2 * right->length; + } else if (num_sides == 3) { + required_size = top->length + 2 * right->length + + bottom->length; + } else { + required_size = top->length + right->length + + bottom->length + left->length; + } + + error = css_stylesheet_style_create(c->sheet, required_size, &ret); + if (error != CSS_OK) + goto cleanup; + + required_size = 0; + + if (num_sides == 1) { + uint32_t *opv = ((uint32_t *) top->bytecode); + uint8_t flags = getFlags(*opv); + uint16_t value = getValue(*opv); + + memcpy(((uint8_t *) ret->bytecode) + required_size, + top->bytecode, top->length); + required_size += top->length; + + *opv = buildOPV(CSS_PROP_PADDING_RIGHT, flags, value); + memcpy(((uint8_t *) ret->bytecode) + required_size, + top->bytecode, top->length); + required_size += top->length; + + *opv = buildOPV(CSS_PROP_PADDING_BOTTOM, flags, value); + memcpy(((uint8_t *) ret->bytecode) + required_size, + top->bytecode, top->length); + required_size += top->length; + + *opv = buildOPV(CSS_PROP_PADDING_LEFT, flags, value); + memcpy(((uint8_t *) ret->bytecode) + required_size, + top->bytecode, top->length); + required_size += top->length; + } else if (num_sides == 2) { + uint32_t *vopv = ((uint32_t *) top->bytecode); + uint32_t *hopv = ((uint32_t *) right->bytecode); + uint8_t vflags = getFlags(*vopv); + uint8_t hflags = getFlags(*hopv); + uint16_t vvalue = getValue(*vopv); + uint16_t hvalue = getValue(*hopv); + + memcpy(((uint8_t *) ret->bytecode) + required_size, + top->bytecode, top->length); + required_size += top->length; + + memcpy(((uint8_t *) ret->bytecode) + required_size, + right->bytecode, right->length); + required_size += right->length; + + *vopv = buildOPV(CSS_PROP_PADDING_BOTTOM, vflags, vvalue); + memcpy(((uint8_t *) ret->bytecode) + required_size, + top->bytecode, top->length); + required_size += top->length; + + *hopv = buildOPV(CSS_PROP_PADDING_LEFT, hflags, hvalue); + memcpy(((uint8_t *) ret->bytecode) + required_size, + right->bytecode, right->length); + required_size += right->length; + } else if (num_sides == 3) { + uint32_t *opv = ((uint32_t *) right->bytecode); + uint8_t flags = getFlags(*opv); + uint16_t value = getValue(*opv); + + memcpy(((uint8_t *) ret->bytecode) + required_size, + top->bytecode, top->length); + required_size += top->length; + + memcpy(((uint8_t *) ret->bytecode) + required_size, + right->bytecode, right->length); + required_size += right->length; + + memcpy(((uint8_t *) ret->bytecode) + required_size, + bottom->bytecode, bottom->length); + required_size += bottom->length; + + *opv = buildOPV(CSS_PROP_PADDING_LEFT, flags, value); + memcpy(((uint8_t *) ret->bytecode) + required_size, + right->bytecode, right->length); + required_size += right->length; + } else { + memcpy(((uint8_t *) ret->bytecode) + required_size, + top->bytecode, top->length); + required_size += top->length; + + memcpy(((uint8_t *) ret->bytecode) + required_size, + right->bytecode, right->length); + required_size += right->length; + + memcpy(((uint8_t *) ret->bytecode) + required_size, + bottom->bytecode, bottom->length); + required_size += bottom->length; + + memcpy(((uint8_t *) ret->bytecode) + required_size, + left->bytecode, left->length); + required_size += left->length; + } + + 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 (top) + css_stylesheet_style_destroy(c->sheet, top); + if (right) + css_stylesheet_style_destroy(c->sheet, right); + if (bottom) + css_stylesheet_style_destroy(c->sheet, bottom); + if (left) + css_stylesheet_style_destroy(c->sheet, left); + if (ret) + css_stylesheet_style_destroy(c->sheet, ret); + + if (error != CSS_OK) + *ctx = orig_ctx; + + return error; +} + /** * Parse padding-bottom * diff --git a/src/parse/properties/properties.c b/src/parse/properties/properties.c index 28b92b7..0f555e1 100644 --- a/src/parse/properties/properties.c +++ b/src/parse/properties/properties.c @@ -87,6 +87,7 @@ const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] = parse_outline_style, parse_outline_width, parse_overflow, + parse_padding, parse_padding_bottom, parse_padding_left, parse_padding_right, diff --git a/src/parse/properties/properties.h b/src/parse/properties/properties.h index 7c7268a..0dc750a 100644 --- a/src/parse/properties/properties.h +++ b/src/parse/properties/properties.h @@ -247,6 +247,9 @@ css_error parse_outline_width(css_language *c, css_error parse_overflow(css_language *c, const parserutils_vector *vector, int *ctx, css_style **result); +css_error parse_padding(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); css_error parse_padding_bottom(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 213595d..906471f 100644 --- a/src/parse/propstrings.c +++ b/src/parse/propstrings.c @@ -117,6 +117,7 @@ const stringmap_entry stringmap[LAST_KNOWN] = { { "outline-style", SLEN("outline-style") }, { "outline-width", SLEN("outline-width") }, { "overflow", SLEN("overflow") }, + { "padding", SLEN("padding") }, { "padding-bottom", SLEN("padding-bottom") }, { "padding-left", SLEN("padding-left") }, { "padding-right", SLEN("padding-right") }, diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h index bff7c4f..9a0eb92 100644 --- a/src/parse/propstrings.h +++ b/src/parse/propstrings.h @@ -48,7 +48,7 @@ enum { MARGIN, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, MAX_HEIGHT, MAX_WIDTH, MIN_HEIGHT, MIN_WIDTH, ORPHANS, OUTLINE, OUTLINE_COLOR, OUTLINE_STYLE, OUTLINE_WIDTH, OVERFLOW, - PADDING_BOTTOM, PADDING_LEFT, PADDING_RIGHT, PADDING_TOP, + PADDING, PADDING_BOTTOM, PADDING_LEFT, PADDING_RIGHT, PADDING_TOP, PAGE_BREAK_AFTER, PAGE_BREAK_BEFORE, PAGE_BREAK_INSIDE, PAUSE, PAUSE_AFTER, PAUSE_BEFORE, PITCH_RANGE, PITCH, PLAY_DURING, POSITION, QUOTES, RICHNESS, RIGHT, SPEAK_HEADER, SPEAK_NUMERAL, -- cgit v1.2.3