summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-06-25 01:26:30 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-06-25 01:26:30 +0000
commita8aacc54b11fd1fc9d84c7d85dd058d3f90e7c32 (patch)
tree0dd82a8963180a42e2e446de8a509cc42b5d171e /src/parse
parent60b5130daa08928bcc86f69b018c0466ebdda582 (diff)
downloadlibcss-a8aacc54b11fd1fc9d84c7d85dd058d3f90e7c32.tar.gz
libcss-a8aacc54b11fd1fc9d84c7d85dd058d3f90e7c32.tar.bz2
Border and outline shorthand property parsers
svn path=/trunk/libcss/; revision=7956
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/properties/border_outline.c1182
-rw-r--r--src/parse/properties/properties.c9
-rw-r--r--src/parse/properties/properties.h27
-rw-r--r--src/parse/propstrings.c9
-rw-r--r--src/parse/propstrings.h40
5 files changed, 1248 insertions, 19 deletions
diff --git a/src/parse/properties/border_outline.c b/src/parse/properties/border_outline.c
index 7245fa6..0c101bc 100644
--- a/src/parse/properties/border_outline.c
+++ b/src/parse/properties/border_outline.c
@@ -5,6 +5,7 @@
* Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
*/
+#include <assert.h>
#include <string.h>
#include "bytecode/bytecode.h"
@@ -12,6 +13,11 @@
#include "parse/properties/properties.h"
#include "parse/properties/utils.h"
+enum { SIDE_TOP = 0, SIDE_RIGHT = 1, SIDE_BOTTOM = 2, SIDE_LEFT = 3 };
+
+static css_error parse_border_side(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ uint32_t side, css_style **result);
static css_error parse_border_side_color(css_language *c,
const parserutils_vector *vector, int *ctx,
uint16_t op, css_style **result);
@@ -22,6 +28,108 @@ static css_error parse_border_side_width(css_language *c,
const parserutils_vector *vector, int *ctx,
uint16_t op, css_style **result);
+/**
+ * Parse border 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_border(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result)
+{
+ int orig_ctx = *ctx;
+ css_style *top = NULL;
+ css_style *right = NULL;
+ css_style *bottom = NULL;
+ css_style *left = NULL;
+ css_style *ret = NULL;
+ uint32_t required_size;
+ css_error error;
+
+ error = parse_border_side(c, vector, ctx, SIDE_TOP, &top);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ *ctx = orig_ctx;
+ error = parse_border_side(c, vector, ctx, SIDE_RIGHT, &right);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ *ctx = orig_ctx;
+ error = parse_border_side(c, vector, ctx, SIDE_BOTTOM, &bottom);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ *ctx = orig_ctx;
+ error = parse_border_side(c, vector, ctx, SIDE_LEFT, &left);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ 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;
+
+ 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);
+
+ *result = ret;
+ 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;
+}
+
+css_error parse_border_bottom(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result)
+{
+ return parse_border_side(c, vector, ctx, SIDE_BOTTOM, result);
+}
+
css_error parse_border_bottom_color(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
@@ -104,6 +212,252 @@ css_error parse_border_collapse(css_language *c,
return CSS_OK;
}
+/**
+ * Parse border-color 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_border_color(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_BORDER_TOP_COLOR,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_RIGHT_COLOR,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_BOTTOM_COLOR,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_LEFT_COLOR,
+ 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 colours */
+ do {
+ prev_ctx = *ctx;
+ error = CSS_OK;
+
+ if (top == NULL &&
+ (error = parse_border_side_color(c, vector,
+ ctx, CSS_PROP_BORDER_TOP_COLOR, &top)) ==
+ CSS_OK) {
+ num_sides = 1;
+ } else if (right == NULL &&
+ (error = parse_border_side_color(c, vector,
+ ctx, CSS_PROP_BORDER_RIGHT_COLOR, &right)) ==
+ CSS_OK) {
+ num_sides = 2;
+ } else if (bottom == NULL &&
+ (error = parse_border_side_color(c, vector,
+ ctx, CSS_PROP_BORDER_BOTTOM_COLOR, &bottom)) ==
+ CSS_OK) {
+ num_sides = 3;
+ } else if (left == NULL &&
+ (error = parse_border_side_color(c, vector,
+ ctx, CSS_PROP_BORDER_LEFT_COLOR, &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_BORDER_RIGHT_COLOR, flags, value);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *opv = buildOPV(CSS_PROP_BORDER_BOTTOM_COLOR, flags, value);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *opv = buildOPV(CSS_PROP_BORDER_LEFT_COLOR, 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_BORDER_BOTTOM_COLOR, vflags, vvalue);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *hopv = buildOPV(CSS_PROP_BORDER_LEFT_COLOR, 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_BORDER_LEFT_COLOR, 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;
+}
+
+css_error parse_border_left(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result)
+{
+ return parse_border_side(c, vector, ctx, SIDE_LEFT, result);
+}
+
css_error parse_border_left_color(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
@@ -128,6 +482,13 @@ css_error parse_border_left_width(css_language *c,
CSS_PROP_BORDER_LEFT_WIDTH, result);
}
+css_error parse_border_right(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result)
+{
+ return parse_border_side(c, vector, ctx, SIDE_RIGHT, result);
+}
+
css_error parse_border_right_color(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
@@ -278,6 +639,252 @@ css_error parse_border_spacing(css_language *c,
return CSS_OK;
}
+/**
+ * Parse border-style 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_border_style(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_BORDER_TOP_STYLE,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_RIGHT_STYLE,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_BOTTOM_STYLE,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_LEFT_STYLE,
+ 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 styles */
+ do {
+ prev_ctx = *ctx;
+ error = CSS_OK;
+
+ if (top == NULL &&
+ (error = parse_border_side_style(c, vector,
+ ctx, CSS_PROP_BORDER_TOP_STYLE, &top)) ==
+ CSS_OK) {
+ num_sides = 1;
+ } else if (right == NULL &&
+ (error = parse_border_side_style(c, vector,
+ ctx, CSS_PROP_BORDER_RIGHT_STYLE, &right)) ==
+ CSS_OK) {
+ num_sides = 2;
+ } else if (bottom == NULL &&
+ (error = parse_border_side_style(c, vector,
+ ctx, CSS_PROP_BORDER_BOTTOM_STYLE, &bottom)) ==
+ CSS_OK) {
+ num_sides = 3;
+ } else if (left == NULL &&
+ (error = parse_border_side_style(c, vector,
+ ctx, CSS_PROP_BORDER_LEFT_STYLE, &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_BORDER_RIGHT_STYLE, flags, value);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *opv = buildOPV(CSS_PROP_BORDER_BOTTOM_STYLE, flags, value);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *opv = buildOPV(CSS_PROP_BORDER_LEFT_STYLE, 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_BORDER_BOTTOM_STYLE, vflags, vvalue);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *hopv = buildOPV(CSS_PROP_BORDER_LEFT_STYLE, 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_BORDER_LEFT_STYLE, 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;
+}
+
+css_error parse_border_top(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result)
+{
+ return parse_border_side(c, vector, ctx, SIDE_TOP, result);
+}
+
css_error parse_border_top_color(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
@@ -303,6 +910,415 @@ css_error parse_border_top_width(css_language *c,
}
/**
+ * Parse border-width 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_border_width(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_BORDER_TOP_WIDTH,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_RIGHT_WIDTH,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_BOTTOM_WIDTH,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_LEFT_WIDTH,
+ 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_border_side_width(c, vector,
+ ctx, CSS_PROP_BORDER_TOP_WIDTH, &top)) ==
+ CSS_OK) {
+ num_sides = 1;
+ } else if (right == NULL &&
+ (error = parse_border_side_width(c, vector,
+ ctx, CSS_PROP_BORDER_RIGHT_WIDTH, &right)) ==
+ CSS_OK) {
+ num_sides = 2;
+ } else if (bottom == NULL &&
+ (error = parse_border_side_width(c, vector,
+ ctx, CSS_PROP_BORDER_BOTTOM_WIDTH, &bottom)) ==
+ CSS_OK) {
+ num_sides = 3;
+ } else if (left == NULL &&
+ (error = parse_border_side_width(c, vector,
+ ctx, CSS_PROP_BORDER_LEFT_WIDTH, &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_BORDER_RIGHT_WIDTH, flags, value);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *opv = buildOPV(CSS_PROP_BORDER_BOTTOM_WIDTH, flags, value);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *opv = buildOPV(CSS_PROP_BORDER_LEFT_WIDTH, 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_BORDER_BOTTOM_WIDTH, vflags, vvalue);
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ top->bytecode, top->length);
+ required_size += top->length;
+
+ *hopv = buildOPV(CSS_PROP_BORDER_LEFT_WIDTH, 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_BORDER_LEFT_WIDTH, 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 outline 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_outline(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 *color = NULL;
+ css_style *style = NULL;
+ css_style *width = 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,
+ 3 * sizeof(uint32_t), &ret);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ bytecode = (uint32_t *) ret->bytecode;
+
+ *(bytecode++) = buildOPV(CSS_PROP_OUTLINE_COLOR,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_OUTLINE_STYLE,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_OUTLINE_WIDTH,
+ 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 individual properties */
+ do {
+ prev_ctx = *ctx;
+ error = CSS_OK;
+
+ if (color == NULL &&
+ (error = parse_outline_color(c, vector,
+ ctx, &color)) == CSS_OK) {
+ } else if (style == NULL &&
+ (error = parse_outline_style(c, vector,
+ ctx, &style)) == CSS_OK) {
+ } else if (width == NULL &&
+ (error = parse_outline_width(c, vector,
+ ctx, &width)) == 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 size of resultant style */
+ required_size = 0;
+ if (color)
+ required_size += color->length;
+ else
+ required_size += sizeof(uint32_t);
+
+ if (style)
+ required_size += style->length;
+ else
+ required_size += sizeof(uint32_t);
+
+ if (width)
+ required_size += width->length;
+ else
+ required_size += sizeof(uint32_t);
+
+ error = css_stylesheet_style_create(c->sheet, required_size, &ret);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ required_size = 0;
+
+ 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_OUTLINE_COLOR,
+ 0, OUTLINE_COLOR_INVERT);
+ required_size += sizeof(uint32_t);
+ }
+
+ if (style) {
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ style->bytecode, style->length);
+ required_size += style->length;
+ } else {
+ void *bc = ((uint8_t *) ret->bytecode) + required_size;
+
+ *((uint32_t *) bc) = buildOPV(CSS_PROP_OUTLINE_STYLE,
+ 0, OUTLINE_STYLE_NONE);
+ required_size += sizeof(uint32_t);
+ }
+
+ if (width) {
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ width->bytecode, width->length);
+ required_size += width->length;
+ } else {
+ void *bc = ((uint8_t *) ret->bytecode) + required_size;
+
+ *((uint32_t *) bc) = buildOPV(CSS_PROP_OUTLINE_WIDTH,
+ 0, OUTLINE_WIDTH_MEDIUM);
+ 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 (color)
+ css_stylesheet_style_destroy(c->sheet, color);
+ if (style)
+ css_stylesheet_style_destroy(c->sheet, style);
+ if (width)
+ css_stylesheet_style_destroy(c->sheet, width);
+ if (ret)
+ css_stylesheet_style_destroy(c->sheet, ret);
+
+ if (error != CSS_OK)
+ *ctx = orig_ctx;
+
+ return error;
+}
+
+/**
* Parse outline-color
*
* \param c Parsing context
@@ -431,6 +1447,172 @@ css_error parse_outline_width(css_language *c,
}
/**
+ * Parse border-{top,right,bottom,left} shorthand
+ *
+ * \param c Parsing context
+ * \param vector Vector of tokens to process
+ * \param ctx Pointer to vector iteration context
+ * \param side The side we're parsing for
+ * \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_border_side(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ uint32_t side, css_style **result)
+{
+ int orig_ctx = *ctx;
+ int prev_ctx;
+ const css_token *token;
+ css_style *color = NULL;
+ css_style *style = NULL;
+ css_style *width = 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,
+ 3 * sizeof(uint32_t), &ret);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ bytecode = (uint32_t *) ret->bytecode;
+
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_TOP_COLOR + side,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_TOP_STYLE + side,
+ FLAG_INHERIT, 0);
+ *(bytecode++) = buildOPV(CSS_PROP_BORDER_TOP_WIDTH + side,
+ 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 individual properties */
+ do {
+ prev_ctx = *ctx;
+ error = CSS_OK;
+
+ if (color == NULL &&
+ (error = parse_border_side_color(c, vector, ctx,
+ CSS_PROP_BORDER_TOP_COLOR + side, &color)) ==
+ CSS_OK) {
+ } else if (style == NULL &&
+ (error = parse_border_side_style(c, vector, ctx,
+ CSS_PROP_BORDER_TOP_STYLE + side, &style)) ==
+ CSS_OK) {
+ } else if (width == NULL &&
+ (error = parse_border_side_width(c, vector, ctx,
+ CSS_PROP_BORDER_TOP_WIDTH + side, &width)) ==
+ 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 size of resultant style */
+ required_size = 0;
+ if (color)
+ required_size += color->length;
+
+ if (style)
+ required_size += style->length;
+ else
+ required_size += sizeof(uint32_t);
+
+ if (width)
+ required_size += width->length;
+ else
+ required_size += sizeof(uint32_t);
+
+ error = css_stylesheet_style_create(c->sheet, required_size, &ret);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ required_size = 0;
+
+ if (color) {
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ color->bytecode, color->length);
+ required_size += color->length;
+ }
+
+ if (style) {
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ style->bytecode, style->length);
+ required_size += style->length;
+ } else {
+ void *bc = ((uint8_t *) ret->bytecode) + required_size;
+
+ *((uint32_t *) bc) = buildOPV(CSS_PROP_BORDER_TOP_STYLE + side,
+ 0, BORDER_STYLE_NONE);
+ required_size += sizeof(uint32_t);
+ }
+
+ if (width) {
+ memcpy(((uint8_t *) ret->bytecode) + required_size,
+ width->bytecode, width->length);
+ required_size += width->length;
+ } else {
+ void *bc = ((uint8_t *) ret->bytecode) + required_size;
+
+ *((uint32_t *) bc) = buildOPV(CSS_PROP_BORDER_TOP_WIDTH + side,
+ 0, BORDER_WIDTH_MEDIUM);
+ 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 (color)
+ css_stylesheet_style_destroy(c->sheet, color);
+ if (style)
+ css_stylesheet_style_destroy(c->sheet, style);
+ if (width)
+ css_stylesheet_style_destroy(c->sheet, width);
+ if (ret)
+ css_stylesheet_style_destroy(c->sheet, ret);
+
+ if (error != CSS_OK)
+ *ctx = orig_ctx;
+
+ return error;
+}
+
+/**
* Parse border-{top,right,bottom,left}-color
*
* \param c Parsing context
diff --git a/src/parse/properties/properties.c b/src/parse/properties/properties.c
index 8da730d..de92933 100644
--- a/src/parse/properties/properties.c
+++ b/src/parse/properties/properties.c
@@ -19,20 +19,28 @@ const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] =
parse_background_image,
parse_background_position,
parse_background_repeat,
+ parse_border,
+ parse_border_bottom,
parse_border_bottom_color,
parse_border_bottom_style,
parse_border_bottom_width,
parse_border_collapse,
+ parse_border_color,
+ parse_border_left,
parse_border_left_color,
parse_border_left_style,
parse_border_left_width,
+ parse_border_right,
parse_border_right_color,
parse_border_right_style,
parse_border_right_width,
parse_border_spacing,
+ parse_border_style,
+ parse_border_top,
parse_border_top_color,
parse_border_top_style,
parse_border_top_width,
+ parse_border_width,
parse_bottom,
parse_caption_side,
parse_clear,
@@ -70,6 +78,7 @@ const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] =
parse_min_height,
parse_min_width,
parse_orphans,
+ parse_outline,
parse_outline_color,
parse_outline_style,
parse_outline_width,
diff --git a/src/parse/properties/properties.h b/src/parse/properties/properties.h
index a41f2c9..78a37d8 100644
--- a/src/parse/properties/properties.h
+++ b/src/parse/properties/properties.h
@@ -43,6 +43,12 @@ css_error parse_background_position(css_language *c,
css_error parse_background_repeat(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
+css_error parse_border(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
+css_error parse_border_bottom(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
css_error parse_border_bottom_color(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
@@ -52,9 +58,15 @@ css_error parse_border_bottom_style(css_language *c,
css_error parse_border_bottom_width(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
+css_error parse_border_color(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
css_error parse_border_collapse(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
+css_error parse_border_left(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
css_error parse_border_left_color(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
@@ -64,6 +76,9 @@ css_error parse_border_left_style(css_language *c,
css_error parse_border_left_width(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
+css_error parse_border_right(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
css_error parse_border_right_color(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
@@ -76,6 +91,12 @@ css_error parse_border_right_width(css_language *c,
css_error parse_border_spacing(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
+css_error parse_border_style(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
+css_error parse_border_top(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
css_error parse_border_top_color(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
@@ -85,6 +106,9 @@ css_error parse_border_top_style(css_language *c,
css_error parse_border_top_width(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
+css_error parse_border_width(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
css_error parse_bottom(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
@@ -196,6 +220,9 @@ css_error parse_min_width(css_language *c,
css_error parse_orphans(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result);
+css_error parse_outline(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style **result);
css_error parse_outline_color(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 2098b60..fbe2d66 100644
--- a/src/parse/propstrings.c
+++ b/src/parse/propstrings.c
@@ -49,20 +49,28 @@ const stringmap_entry stringmap[LAST_KNOWN] = {
{ "background-image", SLEN("background-image") },
{ "background-position", SLEN("background-position") },
{ "background-repeat", SLEN("background-repeat") },
+ { "border", SLEN("border") },
+ { "border-bottom", SLEN("border-bottom") },
{ "border-bottom-color", SLEN("border-bottom-color") },
{ "border-bottom-style", SLEN("border-bottom-style") },
{ "border-bottom-width", SLEN("border-bottom-width") },
{ "border-collapse", SLEN("border-collapse") },
+ { "border-color", SLEN("border-color") },
+ { "border-left", SLEN("border-left") },
{ "border-left-color", SLEN("border-left-color") },
{ "border-left-style", SLEN("border-left-style") },
{ "border-left-width", SLEN("border-left-width") },
+ { "border-right", SLEN("border-right") },
{ "border-right-color", SLEN("border-right-color") },
{ "border-right-style", SLEN("border-right-style") },
{ "border-right-width", SLEN("border-right-width") },
{ "border-spacing", SLEN("border-spacing") },
+ { "border-style", SLEN("border-style") },
+ { "border-top", SLEN("border-top") },
{ "border-top-color", SLEN("border-top-color") },
{ "border-top-style", SLEN("border-top-style") },
{ "border-top-width", SLEN("border-top-width") },
+ { "border-width", SLEN("border-width") },
{ "bottom", SLEN("bottom") },
{ "caption-side", SLEN("caption-side") },
{ "clear", SLEN("clear") },
@@ -100,6 +108,7 @@ const stringmap_entry stringmap[LAST_KNOWN] = {
{ "min-height", SLEN("min-height") },
{ "min-width", SLEN("min-width") },
{ "orphans", SLEN("orphans") },
+ { "outline", SLEN("outline") },
{ "outline-color", SLEN("outline-color") },
{ "outline-style", SLEN("outline-style") },
{ "outline-width", SLEN("outline-width") },
diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h
index 7f25c81..3ea8858 100644
--- a/src/parse/propstrings.h
+++ b/src/parse/propstrings.h
@@ -33,26 +33,28 @@ enum {
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,
+ BACKGROUND_REPEAT, BORDER, BORDER_BOTTOM, BORDER_BOTTOM_COLOR,
+ BORDER_BOTTOM_STYLE, BORDER_BOTTOM_WIDTH, BORDER_COLLAPSE,
+ BORDER_COLOR, BORDER_LEFT, BORDER_LEFT_COLOR, BORDER_LEFT_STYLE,
+ BORDER_LEFT_WIDTH, BORDER_RIGHT, 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,
- LETTER_SPACING, LINE_HEIGHT, LIST_STYLE_IMAGE, LIST_STYLE_POSITION,
- LIST_STYLE_TYPE, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP,
- MAX_HEIGHT, MAX_WIDTH, MIN_HEIGHT, MIN_WIDTH, ORPHANS, OUTLINE_COLOR,
- OUTLINE_STYLE, OUTLINE_WIDTH, OVERFLOW, PADDING_BOTTOM, PADDING_LEFT,
- PADDING_RIGHT, PADDING_TOP, PAGE_BREAK_AFTER, PAGE_BREAK_BEFORE,
- PAGE_BREAK_INSIDE, PAUSE_AFTER, PAUSE_BEFORE, PITCH_RANGE, PITCH,
- PLAY_DURING, POSITION, QUOTES, RICHNESS, RIGHT, SPEAK_HEADER,
- SPEAK_NUMERAL, SPEAK_PUNCTUATION, SPEAK, SPEECH_RATE, STRESS,
- TABLE_LAYOUT, TEXT_ALIGN, TEXT_DECORATION, TEXT_INDENT, TEXT_TRANSFORM,
- TOP, UNICODE_BIDI, VERTICAL_ALIGN, VISIBILITY, VOICE_FAMILY, VOLUME,
- WHITE_SPACE, WIDOWS, WIDTH, WORD_SPACING, Z_INDEX,
+ BORDER_STYLE, BORDER_TOP, BORDER_TOP_COLOR, BORDER_TOP_STYLE,
+ BORDER_TOP_WIDTH, BORDER_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, LETTER_SPACING, LINE_HEIGHT, LIST_STYLE_IMAGE,
+ LIST_STYLE_POSITION, LIST_STYLE_TYPE, 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,
+ PAGE_BREAK_AFTER, PAGE_BREAK_BEFORE, PAGE_BREAK_INSIDE, PAUSE_AFTER,
+ PAUSE_BEFORE, PITCH_RANGE, PITCH, PLAY_DURING, POSITION, QUOTES,
+ RICHNESS, RIGHT, SPEAK_HEADER, SPEAK_NUMERAL, SPEAK_PUNCTUATION, SPEAK,
+ SPEECH_RATE, STRESS, TABLE_LAYOUT, TEXT_ALIGN, TEXT_DECORATION,
+ TEXT_INDENT, TEXT_TRANSFORM, TOP, UNICODE_BIDI, VERTICAL_ALIGN,
+ VISIBILITY, VOICE_FAMILY, VOLUME, WHITE_SPACE, WIDOWS, WIDTH,
+ WORD_SPACING, Z_INDEX,
LAST_PROP = Z_INDEX,