From 0e622a92d6e16141b050a7477d3b23068b289231 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Thu, 25 Jun 2009 21:53:51 +0000 Subject: Font shorthand property svn path=/trunk/libcss/; revision=7989 --- src/parse/properties/font.c | 254 ++++++++++++++++++++++++++++++++++++++ src/parse/properties/properties.c | 1 + src/parse/properties/properties.h | 3 + src/parse/propstrings.c | 1 + src/parse/propstrings.h | 4 +- 5 files changed, 261 insertions(+), 2 deletions(-) (limited to 'src/parse') diff --git a/src/parse/properties/font.c b/src/parse/properties/font.c index e964cba..92726fb 100644 --- a/src/parse/properties/font.c +++ b/src/parse/properties/font.c @@ -5,6 +5,7 @@ * Copyright 2009 John-Mark Bell */ +#include #include #include "bytecode/bytecode.h" @@ -12,6 +13,259 @@ #include "parse/properties/properties.h" #include "parse/properties/utils.h" +/** + * Parse font + * + * \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_font(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 *style = NULL; + css_style *variant = NULL; + css_style *weight = NULL; + css_style *size = NULL; + css_style *line_height = NULL; + css_style *family = NULL; + css_style *ret = NULL; + uint32_t required_size; + int svw; + 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, + 6 * sizeof(uint32_t), &ret); + if (error != CSS_OK) { + *ctx = orig_ctx; + return error; + } + + bytecode = (uint32_t *) ret->bytecode; + + *(bytecode++) = buildOPV(CSS_PROP_FONT_STYLE, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_FONT_VARIANT, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_FONT_WEIGHT, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_FONT_SIZE, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_LINE_HEIGHT, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_FONT_FAMILY, + 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 optional style, variant, and weight */ + for (svw = 0; svw < 3; svw++) { + prev_ctx = *ctx; + error = CSS_OK; + + if (style == NULL && + (error = parse_font_style(c, vector, + ctx, &style)) == CSS_OK) { + } else if (variant == NULL && + (error = parse_font_variant(c, vector, ctx, + &variant)) == CSS_OK) { + } else if (weight == NULL && + (error = parse_font_weight(c, vector, ctx, + &weight)) == CSS_OK) { + } + + if (error == CSS_OK) { + consumeWhitespace(vector, ctx); + + token = parserutils_vector_peek(vector, *ctx); + } else { + break; + } + + if (*ctx == prev_ctx) + break; + } + + consumeWhitespace(vector, ctx); + + /* Now expect a font-size */ + error = parse_font_size(c, vector, ctx, &size); + if (error != CSS_OK) + goto cleanup; + + consumeWhitespace(vector, ctx); + + /* Potential line-height */ + token = parserutils_vector_peek(vector, *ctx); + if (token != NULL && tokenIsChar(token, '/')) { + parserutils_vector_iterate(vector, ctx); + + consumeWhitespace(vector, ctx); + + error = parse_line_height(c, vector, ctx, &line_height); + if (error != CSS_OK) + goto cleanup; + } + + consumeWhitespace(vector, ctx); + + /* Now expect a font-family */ + error = parse_font_family(c, vector, ctx, &family); + if (error != CSS_OK) + goto cleanup; + + /* Must have size and family */ + assert(size != NULL); + assert(family != NULL); + + /* Calculate the required size of the resultant style, + * defaulting the unspecified properties to their initial values */ + required_size = 0; + + if (style) + required_size += style->length; + else + required_size += sizeof(uint32_t); + + if (variant) + required_size += variant->length; + else + required_size += sizeof(uint32_t); + + if (weight) + required_size += weight->length; + else + required_size += sizeof(uint32_t); + + required_size += size->length; + + if (line_height) + required_size += line_height->length; + else + required_size += sizeof(uint32_t); + + required_size += family->length; + + /* Create and populate it */ + error = css_stylesheet_style_create(c->sheet, required_size, &ret); + if (error != CSS_OK) + goto cleanup; + + required_size = 0; + + 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_FONT_STYLE, + 0, FONT_STYLE_NORMAL); + required_size += sizeof(uint32_t); + } + + if (variant) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + variant->bytecode, variant->length); + required_size += variant->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_FONT_VARIANT, + 0, FONT_VARIANT_NORMAL); + required_size += sizeof(uint32_t); + } + + if (weight) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + weight->bytecode, weight->length); + required_size += weight->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_FONT_WEIGHT, + 0, FONT_WEIGHT_NORMAL); + required_size += sizeof(uint32_t); + } + + memcpy(((uint8_t *) ret->bytecode) + required_size, + size->bytecode, size->length); + required_size += size->length; + + if (line_height) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + line_height->bytecode, line_height->length); + required_size += line_height->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_LINE_HEIGHT, + 0, LINE_HEIGHT_NORMAL); + required_size += sizeof(uint32_t); + } + + memcpy(((uint8_t *) ret->bytecode) + required_size, + family->bytecode, family->length); + required_size += family->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 (style) + css_stylesheet_style_destroy(c->sheet, style); + if (variant) + css_stylesheet_style_destroy(c->sheet, variant); + if (weight) + css_stylesheet_style_destroy(c->sheet, weight); + if (size) + css_stylesheet_style_destroy(c->sheet, size); + if (line_height) + css_stylesheet_style_destroy(c->sheet, line_height); + if (family) + css_stylesheet_style_destroy(c->sheet, family); + if (ret) + css_stylesheet_style_destroy(c->sheet, ret); + + if (error != CSS_OK) + *ctx = orig_ctx; + + return error; +} + + /** * Determine if a given font-family ident is reserved * diff --git a/src/parse/properties/properties.c b/src/parse/properties/properties.c index 7e54f16..6e7177b 100644 --- a/src/parse/properties/properties.c +++ b/src/parse/properties/properties.c @@ -58,6 +58,7 @@ const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] = parse_elevation, parse_empty_cells, parse_float, + parse_font, parse_font_family, parse_font_size, parse_font_style, diff --git a/src/parse/properties/properties.h b/src/parse/properties/properties.h index f4d0c8b..9854aed 100644 --- a/src/parse/properties/properties.h +++ b/src/parse/properties/properties.h @@ -160,6 +160,9 @@ css_error parse_empty_cells(css_language *c, css_error parse_float(css_language *c, const parserutils_vector *vector, int *ctx, css_style **result); +css_error parse_font(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); css_error parse_font_family(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 34c849a..e1ef19e 100644 --- a/src/parse/propstrings.c +++ b/src/parse/propstrings.c @@ -88,6 +88,7 @@ const stringmap_entry stringmap[LAST_KNOWN] = { { "elevation", SLEN("elevation") }, { "empty-cells", SLEN("empty-cells") }, { "float", SLEN("float") }, + { "font", SLEN("font") }, { "font-family", SLEN("font-family") }, { "font-size", SLEN("font-size") }, { "font-style", SLEN("font-style") }, diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h index d90803f..fd446ee 100644 --- a/src/parse/propstrings.h +++ b/src/parse/propstrings.h @@ -42,8 +42,8 @@ enum { BORDER_TOP_WIDTH, BORDER_WIDTH, BOTTOM, CAPTION_SIDE, CLEAR, CLIP, COLOR, CONTENT, COUNTER_INCREMENT, COUNTER_RESET, CUE, 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, + FONT, 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, -- cgit v1.2.3