diff options
Diffstat (limited to 'src/parse/properties/border_outline.c')
-rw-r--r-- | src/parse/properties/border_outline.c | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/src/parse/properties/border_outline.c b/src/parse/properties/border_outline.c new file mode 100644 index 0000000..06ba272 --- /dev/null +++ b/src/parse/properties/border_outline.c @@ -0,0 +1,545 @@ +/* + * This file is part of LibCSS. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org> + */ + +#include <string.h> + +#include "bytecode/bytecode.h" +#include "bytecode/opcodes.h" +#include "parse/properties/properties.h" +#include "parse/properties/utils.h" + +static inline css_error parse_border_side_color(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t op, css_style **result); +static inline css_error parse_border_side_style(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t op, css_style **result); +static inline css_error parse_border_side_width(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t op, css_style **result); + +css_error parse_border_bottom_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_color(c, vector, ctx, + CSS_PROP_BORDER_BOTTOM_COLOR, result); +} + +css_error parse_border_bottom_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_style(c, vector, ctx, + CSS_PROP_BORDER_BOTTOM_STYLE, result); +} + +css_error parse_border_bottom_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_width(c, vector, ctx, + CSS_PROP_BORDER_BOTTOM_WIDTH, result); +} + +css_error parse_border_collapse(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (collapse, separate, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->ilower == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->ilower == c->strings[COLLAPSE]) { + value = BORDER_COLLAPSE_COLLAPSE; + } else if (ident->ilower == c->strings[SEPARATE]) { + value = BORDER_COLLAPSE_SEPARATE; + } else + return CSS_INVALID; + + opv = buildOPV(CSS_PROP_BORDER_COLLAPSE, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_border_left_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_color(c, vector, ctx, + CSS_PROP_BORDER_LEFT_COLOR, result); +} + +css_error parse_border_left_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_style(c, vector, ctx, + CSS_PROP_BORDER_LEFT_STYLE, result); +} + +css_error parse_border_left_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_width(c, vector, ctx, + CSS_PROP_BORDER_LEFT_WIDTH, result); +} + +css_error parse_border_right_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_color(c, vector, ctx, + CSS_PROP_BORDER_RIGHT_COLOR, result); +} + +css_error parse_border_right_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_style(c, vector, ctx, + CSS_PROP_BORDER_RIGHT_STYLE, result); +} + +css_error parse_border_right_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_width(c, vector, ctx, + CSS_PROP_BORDER_RIGHT_WIDTH, result); +} + +css_error parse_border_spacing(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + css_fixed length[2] = { 0 }; + uint32_t unit[2] = { 0 }; + uint32_t required_size; + + /* length length? | IDENT(inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else { + int num_lengths = 0; + + error = parse_unit_specifier(c, vector, ctx, UNIT_PX, + &length[0], &unit[0]); + if (error != CSS_OK) + return error; + + if (unit[0] & UNIT_ANGLE || unit[0] & UNIT_TIME || + unit[0] & UNIT_FREQ || unit[0] & UNIT_PCT) + return CSS_INVALID; + + num_lengths = 1; + + consumeWhitespace(vector, ctx); + + token = parserutils_vector_peek(vector, *ctx); + if (token != NULL && tokenIsChar(token, '!') == false) { + error = parse_unit_specifier(c, vector, ctx, UNIT_PX, + &length[1], &unit[1]); + if (error != CSS_OK) + return error; + + if (unit[1] & UNIT_ANGLE || unit[1] & UNIT_TIME || + unit[1] & UNIT_FREQ || + unit[1] & UNIT_PCT) + return CSS_INVALID; + + num_lengths = 2; + } + + if (num_lengths == 1) { + /* Only one length specified. Use for both axes. */ + length[1] = length[0]; + unit[1] = unit[0]; + } + + /* Lengths must not be negative */ + if (length[0] < 0 || length[1] < 0) + return CSS_INVALID; + + value = BORDER_SPACING_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(CSS_PROP_BORDER_SPACING, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == BORDER_SPACING_SET) + required_size += 2 * (sizeof(length[0]) + sizeof(unit[0])); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == BORDER_SPACING_SET) { + uint8_t *ptr = ((uint8_t *) (*result)->bytecode) + sizeof(opv); + + memcpy(ptr, &length[0], sizeof(length[0])); + ptr += sizeof(length[0]); + memcpy(ptr, &unit[0], sizeof(unit[0])); + ptr += sizeof(unit[0]); + memcpy(ptr, &length[1], sizeof(length[1])); + ptr += sizeof(length[1]); + memcpy(ptr, &unit[1], sizeof(unit[1])); + } + + return CSS_OK; +} + +css_error parse_border_top_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_color(c, vector, ctx, + CSS_PROP_BORDER_TOP_COLOR, result); +} + +css_error parse_border_top_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_style(c, vector, ctx, + CSS_PROP_BORDER_TOP_STYLE, result); +} + +css_error parse_border_top_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_width(c, vector, ctx, + CSS_PROP_BORDER_TOP_WIDTH, result); +} + +css_error parse_outline_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t colour = 0; + uint32_t required_size; + + /* colour | IDENT (invert, inherit) */ + token= parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[INVERT]) { + parserutils_vector_iterate(vector, ctx); + value = OUTLINE_COLOR_INVERT; + } else { + error = parse_colour_specifier(c, vector, ctx, &colour); + if (error != CSS_OK) + return error; + + value = OUTLINE_COLOR_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(CSS_PROP_OUTLINE_COLOR, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == OUTLINE_COLOR_SET) + required_size += sizeof(colour); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == OUTLINE_COLOR_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &colour, sizeof(colour)); + } + + return CSS_OK; +} + +css_error parse_outline_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + uint32_t opv; + uint16_t value; + + /* Parse as a border style */ + error = parse_border_side_style(c, vector, ctx, + CSS_PROP_OUTLINE_STYLE, result); + if (error != CSS_OK) + return error; + + opv = *((uint32_t *) (*result)->bytecode); + + value = getValue(opv); + + /* Hidden is invalid */ + if (value == BORDER_STYLE_HIDDEN) + return CSS_INVALID; + + return CSS_OK; +} + +css_error parse_outline_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /* Parse as border width */ + return parse_border_side_width(c, vector, ctx, + CSS_PROP_OUTLINE_WIDTH, result); +} + +css_error parse_border_side_color(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t op, css_style **result) +{ + css_error error; + const css_token *token; + uint32_t opv; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t colour = 0; + uint32_t required_size; + + /* colour | IDENT (transparent, inherit) */ + token= parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[TRANSPARENT]) { + parserutils_vector_iterate(vector, ctx); + value = BORDER_COLOR_TRANSPARENT; + } else { + error = parse_colour_specifier(c, vector, ctx, &colour); + if (error != CSS_OK) + return error; + + value = BORDER_COLOR_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(op, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == BORDER_COLOR_SET) + required_size += sizeof(colour); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == BORDER_COLOR_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &colour, sizeof(colour)); + } + + return CSS_OK; +} + +css_error parse_border_side_style(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t op, css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (none, hidden, dotted, dashed, solid, double, groove, + * ridge, inset, outset, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->ilower == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->ilower == c->strings[NONE]) { + value = BORDER_STYLE_NONE; + } else if (ident->ilower == c->strings[HIDDEN]) { + value = BORDER_STYLE_HIDDEN; + } else if (ident->ilower == c->strings[DOTTED]) { + value = BORDER_STYLE_DOTTED; + } else if (ident->ilower == c->strings[DASHED]) { + value = BORDER_STYLE_DASHED; + } else if (ident->ilower == c->strings[SOLID]) { + value = BORDER_STYLE_SOLID; + } else if (ident->ilower == c->strings[DOUBLE]) { + value = BORDER_STYLE_DOUBLE; + } else if (ident->ilower == c->strings[GROOVE]) { + value = BORDER_STYLE_GROOVE; + } else if (ident->ilower == c->strings[RIDGE]) { + value = BORDER_STYLE_RIDGE; + } else if (ident->ilower == c->strings[INSET]) { + value = BORDER_STYLE_INSET; + } else if (ident->ilower == c->strings[OUTSET]) { + value = BORDER_STYLE_OUTSET; + } else + return CSS_INVALID; + + opv = buildOPV(op, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_border_side_width(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t op, css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + css_fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | IDENT(thin, medium, thick, inherit) */ + token= parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[THIN]) { + parserutils_vector_iterate(vector, ctx); + value = BORDER_WIDTH_THIN; + } else if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[MEDIUM]) { + parserutils_vector_iterate(vector, ctx); + value = BORDER_WIDTH_MEDIUM; + } else if (token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[THICK]) { + parserutils_vector_iterate(vector, ctx); + value = BORDER_WIDTH_THICK; + } else { + error = parse_unit_specifier(c, vector, ctx, UNIT_PX, + &length, &unit); + if (error != CSS_OK) + return error; + + if (unit == UNIT_PCT || unit & UNIT_ANGLE || + unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + /* Length must be positive */ + if (length < 0) + return CSS_INVALID; + + value = BORDER_WIDTH_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(op, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == BORDER_WIDTH_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == BORDER_WIDTH_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + |