Пример #1
0
/**
 * Convert a voice-family token into a bytecode value
 *
 * \param c	 Parsing context
 * \param token	 Token to consider
 * \return Bytecode value
 */
static css_code_t voice_family_value(css_language *c, const css_token *token, bool first)
{
	uint16_t value;
	bool match;

	if (token->type == CSS_TOKEN_IDENT) {
		if ((lwc_string_caseless_isequal(
				token->idata, c->strings[MALE],
				&match) == lwc_error_ok && match))
			value = VOICE_FAMILY_MALE;
		else if ((lwc_string_caseless_isequal(
				token->idata, c->strings[FEMALE],
				&match) == lwc_error_ok && match))
			value = VOICE_FAMILY_FEMALE;
		else if ((lwc_string_caseless_isequal(
				token->idata, c->strings[CHILD],
				&match) == lwc_error_ok && match))
			value = VOICE_FAMILY_CHILD;
		else
			value = VOICE_FAMILY_IDENT_LIST;
	} else {
		value = VOICE_FAMILY_STRING;
	}

	return first ? buildOPV(CSS_PROP_VOICE_FAMILY, 0, value) : value;
}
Пример #2
0
/**
 * Parse overflow
 *
 * \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_overflow(css_language *c, 
		const parserutils_vector *vector, int *ctx, 
		css_style **result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *ident;
	uint8_t flags = 0;
	uint16_t value = 0;
	uint32_t opv;
	bool match;

	/* IDENT (visible, hidden, scroll, auto, inherit) */
	ident = parserutils_vector_iterate(vector, ctx);
	if (ident == NULL || ident->type != CSS_TOKEN_IDENT) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[INHERIT],
			&match) == lwc_error_ok && match)) {
		flags |= FLAG_INHERIT;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[VISIBLE],
			&match) == lwc_error_ok && match)) {
		value = OVERFLOW_VISIBLE;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[HIDDEN],
			&match) == lwc_error_ok && match)) {
		value = OVERFLOW_HIDDEN;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[SCROLL],
			&match) == lwc_error_ok && match)) {
		value = OVERFLOW_SCROLL;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[AUTO],
			&match) == lwc_error_ok && match)) {
		value = OVERFLOW_AUTO;
	} else {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	opv = buildOPV(CSS_PROP_OVERFLOW, flags, value);

	/* Allocate result */
	error = css_stylesheet_style_create(c->sheet, sizeof(opv), result);
	if (error != CSS_OK) {
		*ctx = orig_ctx;
		return error;
	}

	/* Copy the bytecode to it */
	memcpy((*result)->bytecode, &opv, sizeof(opv));

	return CSS_OK;
}
Пример #3
0
/**
 * Parse width
 *
 * \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_width(css_language *c, 
		const parserutils_vector *vector, int *ctx, 
		css_style **result)
{
	int orig_ctx = *ctx;
	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;
	bool match;

	/* length | percentage | IDENT(auto, inherit) */
	token = parserutils_vector_peek(vector, *ctx);
	if (token == NULL) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[INHERIT],
			&match) == lwc_error_ok && match)) {
		parserutils_vector_iterate(vector, ctx);
		flags = FLAG_INHERIT;
	} else if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[AUTO],
			&match) == lwc_error_ok && match)) {
		parserutils_vector_iterate(vector, ctx);
		value = WIDTH_AUTO;
	} else {
		error = parse_unit_specifier(c, vector, ctx, UNIT_PX,
				&length, &unit);
		if (error != CSS_OK) {
			*ctx = orig_ctx;
			return error;
		}

		if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}

		/* Must be positive */
		if (length < 0) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}

		value = WIDTH_SET;
	}

	opv = buildOPV(CSS_PROP_WIDTH, flags, value);

	required_size = sizeof(opv);
	if ((flags & FLAG_INHERIT) == false && value == WIDTH_SET)
		required_size += sizeof(length) + sizeof(unit);

	/* Allocate result */
	error = css_stylesheet_style_create(c->sheet, required_size, result);
	if (error != CSS_OK) {
		*ctx = orig_ctx;
		return error;
	}

	/* Copy the bytecode to it */
	memcpy((*result)->bytecode, &opv, sizeof(opv));
	if ((flags & FLAG_INHERIT) == false && value == 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;
}
Пример #4
0
/**
 * Parse display
 *
 * \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_display(css_language *c, 
		const parserutils_vector *vector, int *ctx, 
		css_style **result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *ident;
	uint8_t flags = 0;
	uint16_t value = 0;
	uint32_t opv;
	bool match;

	/* IDENT (inline, block, list-item, run-in, inline-block, table,
	 * inline-table, table-row-group, table-header-group, 
	 * table-footer-group, table-row, table-column-group, table-column,
	 * table-cell, table-caption, none, inherit) */
	ident = parserutils_vector_iterate(vector, ctx);
	if (ident == NULL || ident->type != CSS_TOKEN_IDENT) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[INHERIT],
			&match) == lwc_error_ok && match)) {
		flags |= FLAG_INHERIT;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[INLINE],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_INLINE;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[BLOCK],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_BLOCK;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[LIST_ITEM],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_LIST_ITEM;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[RUN_IN],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_RUN_IN;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[INLINE_BLOCK],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_INLINE_BLOCK;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[INLINE_TABLE],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_INLINE_TABLE;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE_ROW_GROUP],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE_ROW_GROUP;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE_HEADER_GROUP],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE_HEADER_GROUP;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE_FOOTER_GROUP],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE_FOOTER_GROUP;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE_ROW],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE_ROW;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE_COLUMN_GROUP],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE_COLUMN_GROUP;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE_COLUMN],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE_COLUMN;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE_CELL],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE_CELL;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[TABLE_CAPTION],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_TABLE_CAPTION;
	} else if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[NONE],
			&match) == lwc_error_ok && match)) {
		value = DISPLAY_NONE;
	} else {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	opv = buildOPV(CSS_PROP_DISPLAY, flags, value);

	/* Allocate result */
	error = css_stylesheet_style_create(c->sheet, sizeof(opv), result);
	if (error != CSS_OK) {
		*ctx = orig_ctx;
		return error;
	}

	/* Copy the bytecode to it */
	memcpy((*result)->bytecode, &opv, sizeof(opv));

	return CSS_OK;
}
Пример #5
0
/**
 * Parse line-height
 *
 * \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_line_height(css_language *c, 
		const parserutils_vector *vector, int *ctx, 
		css_style **result)
{
	int orig_ctx = *ctx;
	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;
	bool match;

	/* number | length | percentage | IDENT(normal, inherit) */
	token = parserutils_vector_peek(vector, *ctx);
	if (token == NULL) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[INHERIT],
			&match) == lwc_error_ok && match)) {
		parserutils_vector_iterate(vector, ctx);
		flags = FLAG_INHERIT;
	} else if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[NORMAL],
			&match) == lwc_error_ok && match)) {
		parserutils_vector_iterate(vector, ctx);
		value = LINE_HEIGHT_NORMAL;
	} else if (token->type == CSS_TOKEN_NUMBER) {
		size_t consumed = 0;
		length = number_from_lwc_string(token->idata, false, &consumed);
		if (consumed != lwc_string_length(token->idata)) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}

		/* Negative values are illegal */
		if (length < 0) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}

		parserutils_vector_iterate(vector, ctx);
		value = LINE_HEIGHT_NUMBER;
	} else {
		error = parse_unit_specifier(c, vector, ctx, UNIT_PX,
				&length, &unit);
		if (error != CSS_OK) {
			*ctx = orig_ctx;
			return error;
		}

		if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}

		/* Negative values are illegal */
		if (length < 0) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}

		value = LINE_HEIGHT_DIMENSION;
	}

	opv = buildOPV(CSS_PROP_LINE_HEIGHT, flags, value);

	required_size = sizeof(opv);
	if ((flags & FLAG_INHERIT) == false && value == LINE_HEIGHT_NUMBER)
		required_size += sizeof(length);
	else if ((flags & FLAG_INHERIT) == false && 
			value == LINE_HEIGHT_DIMENSION)
		required_size += sizeof(length) + sizeof(unit);

	/* Allocate result */
	error = css_stylesheet_style_create(c->sheet, required_size, result);
	if (error != CSS_OK) {
		*ctx = orig_ctx;
		return error;
	}

	/* Copy the bytecode to it */
	memcpy((*result)->bytecode, &opv, sizeof(opv));
	if ((flags & FLAG_INHERIT) == false && (value == LINE_HEIGHT_NUMBER || 
			value == LINE_HEIGHT_DIMENSION))
		memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv),
				&length, sizeof(length));
	if ((flags & FLAG_INHERIT) == false && value == LINE_HEIGHT_DIMENSION)
		memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) +
				sizeof(length), &unit, sizeof(unit));

	return CSS_OK;
}
Пример #6
0
/**
 * Make a style important
 *
 * \param style  The style to modify
 */
void css__make_style_important(css_style *style)
{
	css_code_t *bytecode = style->bytecode;
	uint32_t length = style->used;
	uint32_t offset = 0;

	while (offset < length) {
		opcode_t op;
		uint8_t flags;
		uint32_t value;
		css_code_t opv = bytecode[offset];

		/* Extract opv components, setting important flag */
		op = getOpcode(opv);
		flags = getFlags(opv) | FLAG_IMPORTANT;
		value = getValue(opv);

		/* Write OPV back to bytecode */
		bytecode[offset] = buildOPV(op, flags, value);

		offset++;

		/* Advance past any property-specific data */
		if (isInherit(opv) == false) {
			switch (op) {
			case CSS_PROP_AZIMUTH:
				if ((value & ~AZIMUTH_BEHIND) == AZIMUTH_ANGLE)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_BORDER_TOP_COLOR:
			case CSS_PROP_BORDER_RIGHT_COLOR:
			case CSS_PROP_BORDER_BOTTOM_COLOR:
			case CSS_PROP_BORDER_LEFT_COLOR:
			case CSS_PROP_BACKGROUND_COLOR:
			case CSS_PROP_COLUMN_RULE_COLOR:
				assert(BACKGROUND_COLOR_SET == 
				       (enum op_background_color)BORDER_COLOR_SET);
				assert(BACKGROUND_COLOR_SET == 
				       (enum op_background_color)COLUMN_RULE_COLOR_SET);

				if (value == BACKGROUND_COLOR_SET)
					offset++; /* colour */
				break;

			case CSS_PROP_BACKGROUND_IMAGE:
			case CSS_PROP_CUE_AFTER:
			case CSS_PROP_CUE_BEFORE:
			case CSS_PROP_LIST_STYLE_IMAGE:
				assert(BACKGROUND_IMAGE_URI == 
				       (enum op_background_image)CUE_AFTER_URI);
				assert(BACKGROUND_IMAGE_URI == 
				       (enum op_background_image)CUE_BEFORE_URI);
				assert(BACKGROUND_IMAGE_URI ==
				       (enum op_background_image)LIST_STYLE_IMAGE_URI);

				if (value == BACKGROUND_IMAGE_URI) 
					offset++; /* string table entry */
				break;

			case CSS_PROP_BACKGROUND_POSITION:
				if ((value & 0xf0) == BACKGROUND_POSITION_HORZ_SET)
					offset += 2; /* length + units */

				if ((value & 0x0f) == BACKGROUND_POSITION_VERT_SET)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_BORDER_SPACING:
				if (value == BORDER_SPACING_SET)
					offset += 4; /* two length + units */
				break;

			case CSS_PROP_BORDER_TOP_WIDTH:
			case CSS_PROP_BORDER_RIGHT_WIDTH:
			case CSS_PROP_BORDER_BOTTOM_WIDTH:
			case CSS_PROP_BORDER_LEFT_WIDTH:
			case CSS_PROP_OUTLINE_WIDTH:
			case CSS_PROP_COLUMN_RULE_WIDTH:
				assert(BORDER_WIDTH_SET == 
				       (enum op_border_width)OUTLINE_WIDTH_SET);
				assert(BORDER_WIDTH_SET ==
				       (enum op_border_width)COLUMN_RULE_WIDTH_SET);

				if (value == BORDER_WIDTH_SET)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_MARGIN_TOP:
			case CSS_PROP_MARGIN_RIGHT:
			case CSS_PROP_MARGIN_BOTTOM:
			case CSS_PROP_MARGIN_LEFT:
			case CSS_PROP_BOTTOM:
			case CSS_PROP_LEFT:
			case CSS_PROP_RIGHT:
			case CSS_PROP_TOP:
			case CSS_PROP_HEIGHT:
			case CSS_PROP_WIDTH:
			case CSS_PROP_COLUMN_WIDTH:
			case CSS_PROP_COLUMN_GAP:
				assert(BOTTOM_SET == (enum op_bottom)LEFT_SET);
				assert(BOTTOM_SET == (enum op_bottom)RIGHT_SET);
				assert(BOTTOM_SET == (enum op_bottom)TOP_SET);
				assert(BOTTOM_SET == (enum op_bottom)HEIGHT_SET);
				assert(BOTTOM_SET == (enum op_bottom)MARGIN_SET);
				assert(BOTTOM_SET == (enum op_bottom)WIDTH_SET);
				assert(BOTTOM_SET == (enum op_bottom)COLUMN_WIDTH_SET);
				assert(BOTTOM_SET == (enum op_bottom)COLUMN_GAP_SET);

				if (value == BOTTOM_SET) 
					offset += 2; /* length + units */
				break;

			case CSS_PROP_CLIP:
				if ((value & CLIP_SHAPE_MASK) == CLIP_SHAPE_RECT) {
					if ((value & CLIP_RECT_TOP_AUTO) == 0)
						offset += 2; /* length + units */

					if ((value & CLIP_RECT_RIGHT_AUTO) == 0)
						offset += 2; /* length + units */

					if ((value & CLIP_RECT_BOTTOM_AUTO) == 0)
						offset += 2; /* length + units */

					if ((value & CLIP_RECT_LEFT_AUTO) == 0)
						offset += 2; /* length + units */

				}
				break;

			case CSS_PROP_COLOR:
				if (value == COLOR_SET)
					offset++; /* colour */
				break;

			case CSS_PROP_COLUMN_COUNT:
				if (value == COLUMN_COUNT_SET)
					offset++; /* colour */
				break;

			case CSS_PROP_CONTENT:
				while (value != CONTENT_NORMAL &&
						value != CONTENT_NONE) {
					switch (value & 0xff) {
					case CONTENT_COUNTER:
					case CONTENT_URI:
					case CONTENT_ATTR:
					case CONTENT_STRING:
						offset++; /* string table entry */
						break;

					case CONTENT_COUNTERS:
						offset+=2; /* two string entries */
						break;

					case CONTENT_OPEN_QUOTE:
					case CONTENT_CLOSE_QUOTE:
					case CONTENT_NO_OPEN_QUOTE:
					case CONTENT_NO_CLOSE_QUOTE:
						break;
					}

					value = bytecode[offset];
				        offset++;
				}
				break;

			case CSS_PROP_COUNTER_INCREMENT:
			case CSS_PROP_COUNTER_RESET:
				assert(COUNTER_INCREMENT_NONE == 
				       (enum op_counter_increment)COUNTER_RESET_NONE);

				while (value != COUNTER_INCREMENT_NONE) {
					offset+=2; /* string + integer */

					value = bytecode[offset];
				        offset++;
				}
				break;

			case CSS_PROP_CURSOR:
				while (value == CURSOR_URI) {
					offset++; /* string table entry */

					value = bytecode[offset];
				        offset++;
				}
				break;

			case CSS_PROP_ELEVATION:
				if (value == ELEVATION_ANGLE)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_FONT_FAMILY:
				while (value != FONT_FAMILY_END) {
					switch (value) {
					case FONT_FAMILY_STRING:
					case FONT_FAMILY_IDENT_LIST:
						offset++; /* string table entry */
						break;
					}

					value = bytecode[offset];
				        offset++;
				}
				break;

			case CSS_PROP_FONT_SIZE:
				if (value == FONT_SIZE_DIMENSION) 
					offset += 2; /* length + units */
				break;

			case CSS_PROP_LETTER_SPACING:
			case CSS_PROP_WORD_SPACING:
				assert(LETTER_SPACING_SET == 
				       (enum op_letter_spacing)WORD_SPACING_SET);

				if (value == LETTER_SPACING_SET)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_LINE_HEIGHT:
				switch (value) {
				case LINE_HEIGHT_NUMBER:
					offset++; /* value */
					break;

				case LINE_HEIGHT_DIMENSION:
					offset += 2; /* length + units */
					break;
				}
				break;

			case CSS_PROP_MAX_HEIGHT:
			case CSS_PROP_MAX_WIDTH:
				assert(MAX_HEIGHT_SET == 
				       (enum op_max_height)MAX_WIDTH_SET);

				if (value == MAX_HEIGHT_SET)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_PADDING_TOP:
			case CSS_PROP_PADDING_RIGHT:
			case CSS_PROP_PADDING_BOTTOM:
			case CSS_PROP_PADDING_LEFT:
			case CSS_PROP_MIN_HEIGHT:
			case CSS_PROP_MIN_WIDTH:
			case CSS_PROP_PAUSE_AFTER:
			case CSS_PROP_PAUSE_BEFORE:
			case CSS_PROP_TEXT_INDENT:
				assert(MIN_HEIGHT_SET == (enum op_min_height)MIN_WIDTH_SET);
				assert(MIN_HEIGHT_SET == (enum op_min_height)PADDING_SET);
				assert(MIN_HEIGHT_SET == (enum op_min_height)PAUSE_AFTER_SET);
				assert(MIN_HEIGHT_SET == (enum op_min_height)PAUSE_BEFORE_SET);
				assert(MIN_HEIGHT_SET == (enum op_min_height)TEXT_INDENT_SET);

				if (value == MIN_HEIGHT_SET)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_OPACITY:
				if (value == OPACITY_SET)
					offset++; /* value */
				break;

			case CSS_PROP_ORPHANS:
			case CSS_PROP_PITCH_RANGE:
			case CSS_PROP_RICHNESS:
			case CSS_PROP_STRESS:
			case CSS_PROP_WIDOWS:
            case CSS_PROP_FLEX_GROW:
            case CSS_PROP_FLEX_SHRINK:
            case CSS_PROP_FLEX_BASIS:
				assert(ORPHANS_SET == (enum op_orphans)PITCH_RANGE_SET);
				assert(ORPHANS_SET == (enum op_orphans)RICHNESS_SET);
				assert(ORPHANS_SET == (enum op_orphans)STRESS_SET);
				assert(ORPHANS_SET == (enum op_orphans)WIDOWS_SET);
                assert(ORPHANS_SET == (enum op_orphans)FLEX_GROW_SET);
                assert(ORPHANS_SET == (enum op_orphans)FLEX_SHRINK_SET);
                assert(ORPHANS_SET == (enum op_orphans)FLEX_BASIS_SET);

				if (value == ORPHANS_SET)
					offset++; /* value */
				break;

			case CSS_PROP_OUTLINE_COLOR:
				if (value == OUTLINE_COLOR_SET)
					offset++; /* color */
				break;

			case CSS_PROP_PITCH:
				if (value == PITCH_FREQUENCY)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_PLAY_DURING:
				if (value & PLAY_DURING_URI)
					offset++; /* string table entry */
				break;

			case CSS_PROP_QUOTES:
				while (value != QUOTES_NONE) {
					offset += 2; /* two string table entries */

					value = bytecode[offset];
				        offset++;
				}
				break;

			case CSS_PROP_SPEECH_RATE:
				if (value == SPEECH_RATE_SET) 
					offset++; /* rate */
				break;

			case CSS_PROP_VERTICAL_ALIGN:
				if (value == VERTICAL_ALIGN_SET)
					offset += 2; /* length + units */
				break;

			case CSS_PROP_VOICE_FAMILY:
				while (value != VOICE_FAMILY_END) {
					switch (value) {
					case VOICE_FAMILY_STRING:
					case VOICE_FAMILY_IDENT_LIST:
						offset++; /* string table entry */
						break;
					}

					value = bytecode[offset];
				        offset++;
				}
				break;

			case CSS_PROP_VOLUME:
				switch (value) {
				case VOLUME_NUMBER:
					offset++; /* value */
					break;

				case VOLUME_DIMENSION:
					offset += 2; /* value + units */
					break;
				}
				break;

			case CSS_PROP_Z_INDEX:
				if (value == Z_INDEX_SET)
					offset++; /* z index */
				break;

			default:
				break;
			}
		}
	}

}
Пример #7
0
/**
 * Parse z-index
 *
 * \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_z_index(css_language *c, 
		const parserutils_vector *vector, int *ctx, 
		css_style **result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *token;
	uint8_t flags = 0;
	uint16_t value = 0;
	uint32_t opv;
	css_fixed num = 0;
	uint32_t required_size;
	bool match;

	/* <integer> | IDENT (auto, inherit) */
	token = parserutils_vector_iterate(vector, ctx);
	if (token == NULL || (token->type != CSS_TOKEN_IDENT &&
			token->type != CSS_TOKEN_NUMBER)) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[INHERIT],
			&match) == lwc_error_ok && match)) {
		flags |= FLAG_INHERIT;
	} else if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[AUTO],
			&match) == lwc_error_ok && match)) {
		value = Z_INDEX_AUTO;
	} else if (token->type == CSS_TOKEN_NUMBER) {
		size_t consumed = 0;
		num = number_from_lwc_string(token->idata, true, &consumed);
		/* Invalid if there are trailing characters */
		if (consumed != lwc_string_length(token->idata)) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}

		value = Z_INDEX_SET;
	} else {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	opv = buildOPV(CSS_PROP_Z_INDEX, flags, value);

	required_size = sizeof(opv);
	if ((flags & FLAG_INHERIT) == false && value == Z_INDEX_SET)
		required_size += sizeof(num);

	/* Allocate result */
	error = css_stylesheet_style_create(c->sheet, required_size, result);
	if (error != CSS_OK) {
		*ctx = orig_ctx;
		return error;
	}

	/* Copy the bytecode to it */
	memcpy((*result)->bytecode, &opv, sizeof(opv));
	if ((flags & FLAG_INHERIT) == false && value == Z_INDEX_SET) {
		memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), 
				&num, sizeof(num));
	}

	return CSS_OK;
}
Пример #8
0
/**
 * Parse clip
 *
 * \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_clip(css_language *c, 
		const parserutils_vector *vector, int *ctx, 
		css_style **result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *token;
	uint8_t flags = 0;
	uint16_t value = 0;
	uint32_t opv;
	int num_lengths = 0;
	css_fixed length[4] = { 0 };
	uint32_t unit[4] = { 0 };
	uint32_t required_size;
	bool match;

	/* FUNCTION(rect) [ [ IDENT(auto) | length ] CHAR(,)? ]{3} 
	 *                [ IDENT(auto) | length ] CHAR{)} |
	 * IDENT(auto, inherit) */
	token = parserutils_vector_iterate(vector, ctx);
	if (token == NULL) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[INHERIT],
			&match) == lwc_error_ok && match)) {
		flags = FLAG_INHERIT;
	} else if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[AUTO],
			&match) == lwc_error_ok && match)) {
		value = CLIP_AUTO;
	} else if (token->type == CSS_TOKEN_FUNCTION &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[RECT],
			&match) == lwc_error_ok && match)) {
		int i;
		value = CLIP_SHAPE_RECT;

		for (i = 0; i < 4; i++) {
			consumeWhitespace(vector, ctx);

			token = parserutils_vector_peek(vector, *ctx);
			if (token == NULL) {
				*ctx = orig_ctx;
				return CSS_INVALID;
			}

			if (token->type == CSS_TOKEN_IDENT) {
				/* Slightly magical way of generating the auto 
				 * values. These are bits 3-6 of the value. */
				if ((lwc_string_caseless_isequal(
						token->idata, c->strings[AUTO],
						&match) == lwc_error_ok && 
						match))
					value |= 1 << (i + 3);
				else {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				parserutils_vector_iterate(vector, ctx);
			} else {
				error = parse_unit_specifier(c, vector, ctx, 
						UNIT_PX, 
						&length[num_lengths], 
						&unit[num_lengths]);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				if (unit[num_lengths] & UNIT_ANGLE || 
						unit[num_lengths] & UNIT_TIME ||
						unit[num_lengths] & UNIT_FREQ ||
						unit[num_lengths] & UNIT_PCT) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				num_lengths++;
			}

			consumeWhitespace(vector, ctx);

			/* Consume optional comma after first 3 parameters */
			if (i < 3) {
				token = parserutils_vector_peek(vector, *ctx);
				if (token == NULL) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				if (tokenIsChar(token, ','))
					parserutils_vector_iterate(vector, ctx);
			}
		}

		consumeWhitespace(vector, ctx);

		/* Finally, consume closing parenthesis */
		token = parserutils_vector_iterate(vector, ctx);
		if (token == NULL || tokenIsChar(token, ')') == false) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}
	} else {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	opv = buildOPV(CSS_PROP_CLIP, flags, value);

	required_size = sizeof(opv);
	if ((flags & FLAG_INHERIT) == false && 
			(value & CLIP_SHAPE_MASK) == CLIP_SHAPE_RECT) {
		required_size += 
			num_lengths * (sizeof(length[0]) + sizeof(unit[0]));
	}

	/* Allocate result */
	error = css_stylesheet_style_create(c->sheet, required_size, result);
	if (error != CSS_OK) {
		*ctx = orig_ctx;
		return error;
	}

	/* Copy the bytecode to it */
	memcpy((*result)->bytecode, &opv, sizeof(opv));
	if ((flags & FLAG_INHERIT) == false && 
			(value & CLIP_SHAPE_MASK) == CLIP_SHAPE_RECT) {
		int i;
		uint8_t *ptr = ((uint8_t *) (*result)->bytecode) + sizeof(opv);

		for (i = 0; i < num_lengths; i++) {
			memcpy(ptr, &length[i], sizeof(length[i]));
			ptr += sizeof(length[i]);
			memcpy(ptr, &unit[i], sizeof(unit[i]));
			ptr += sizeof(unit[i]);
		}
	}

	return CSS_OK;
}