Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3584 sourcerer 1
/*
2
 * This file is part of LibCSS.
3
 * Licensed under the MIT License,
4
 *		  http://www.opensource.org/licenses/mit-license.php
5
 * Copyright 2009 John-Mark Bell 
6
 */
7
 
8
#include 
9
#include 
10
 
11
#include "bytecode/bytecode.h"
12
#include "bytecode/opcodes.h"
13
#include "parse/properties/properties.h"
14
#include "parse/properties/utils.h"
15
 
16
/**
17
 * Parse background-position
18
 *
19
 * \param c	  Parsing context
20
 * \param vector  Vector of tokens to process
21
 * \param ctx	  Pointer to vector iteration context
22
 * \param result  Pointer to location to receive resulting style
23
 * \return CSS_OK on success,
24
 *	   CSS_NOMEM on memory exhaustion,
25
 *	   CSS_INVALID if the input is not valid
26
 *
27
 * Post condition: \a *ctx is updated with the next token to process
28
 *		   If the input is invalid, then \a *ctx remains unchanged.
29
 */
30
css_error css__parse_background_position(css_language *c,
31
		const parserutils_vector *vector, int *ctx,
32
		css_style *result)
33
{
34
	int orig_ctx = *ctx;
35
	css_error error;
36
	const css_token *token;
37
	uint8_t flags = 0;
38
	uint16_t value[2] = { 0 };
39
	css_fixed length[2] = { 0 };
40
	uint32_t unit[2] = { 0 };
41
	bool match;
42
 
43
	/* [length | percentage | IDENT(left, right, top, bottom, center)]{1,2}
44
	 * | IDENT(inherit) */
45
	token = parserutils_vector_peek(vector, *ctx);
46
	if (token == NULL) {
47
		*ctx = orig_ctx;
48
		return CSS_INVALID;
49
	}
50
 
51
	if (token->type == CSS_TOKEN_IDENT &&
52
			(lwc_string_caseless_isequal(
53
			token->idata, c->strings[INHERIT],
54
			&match) == lwc_error_ok && match)) {
55
		parserutils_vector_iterate(vector, ctx);
56
		flags = FLAG_INHERIT;
57
	} else {
58
		int i;
59
 
60
		for (i = 0; i < 2; i++) {
61
			token = parserutils_vector_peek(vector, *ctx);
62
			if (token == NULL)
63
				break;
64
 
65
			if (token->type == CSS_TOKEN_IDENT) {
66
				if ((lwc_string_caseless_isequal(
67
						token->idata, c->strings[LEFT],
68
						&match) == lwc_error_ok &&
69
						match)) {
70
					value[i] =
71
						BACKGROUND_POSITION_HORZ_LEFT;
72
				} else if ((lwc_string_caseless_isequal(
73
						token->idata, c->strings[RIGHT],
74
						&match) == lwc_error_ok &&
75
						match)) {
76
					value[i] =
77
						BACKGROUND_POSITION_HORZ_RIGHT;
78
				} else if ((lwc_string_caseless_isequal(
79
						token->idata, c->strings[TOP],
80
						&match) == lwc_error_ok &&
81
						match)) {
82
					value[i] = BACKGROUND_POSITION_VERT_TOP;
83
				} else if ((lwc_string_caseless_isequal(
84
						token->idata,
85
						c->strings[BOTTOM],
86
						&match) == lwc_error_ok &&
87
						match)) {
88
					value[i] =
89
						BACKGROUND_POSITION_VERT_BOTTOM;
90
				} else if ((lwc_string_caseless_isequal(
91
						token->idata,
92
						c->strings[CENTER],
93
						&match) == lwc_error_ok &&
94
						match)) {
95
					/* We'll fix this up later */
96
					value[i] =
97
						BACKGROUND_POSITION_VERT_CENTER;
98
				} else if (i == 1) {
99
					/* Second pass, so ignore this one */
100
					break;
101
				} else {
102
					/* First pass, so invalid */
103
					*ctx = orig_ctx;
104
					return CSS_INVALID;
105
				}
106
 
107
				parserutils_vector_iterate(vector, ctx);
108
			} else if (token->type == CSS_TOKEN_DIMENSION ||
109
					token->type == CSS_TOKEN_NUMBER ||
110
					token->type == CSS_TOKEN_PERCENTAGE) {
111
				error = css__parse_unit_specifier(c, vector, ctx,
112
						UNIT_PX, &length[i], &unit[i]);
113
				if (error != CSS_OK) {
114
					*ctx = orig_ctx;
115
					return error;
116
				}
117
 
118
				if (unit[i] & UNIT_ANGLE ||
119
						unit[i] & UNIT_TIME ||
120
						unit[i] & UNIT_FREQ) {
121
					*ctx = orig_ctx;
122
					return CSS_INVALID;
123
				}
124
 
125
				/* We'll fix this up later, too */
126
				value[i] = BACKGROUND_POSITION_VERT_SET;
127
			} else {
128
				if (i == 1) {
129
					/* Second pass, so ignore */
130
					break;
131
				} else {
132
					/* First pass, so invalid */
133
					*ctx = orig_ctx;
134
					return CSS_INVALID;
135
				}
136
			}
137
 
138
			consumeWhitespace(vector, ctx);
139
		}
140
 
141
		assert(i != 0);
142
 
143
		/* Now, sort out the mess we've got */
144
		if (i == 1) {
145
			assert(BACKGROUND_POSITION_VERT_CENTER ==
146
					BACKGROUND_POSITION_HORZ_CENTER);
147
 
148
			/* Only one value, so the other is center */
149
			switch (value[0]) {
150
			case BACKGROUND_POSITION_HORZ_LEFT:
151
			case BACKGROUND_POSITION_HORZ_RIGHT:
152
			case BACKGROUND_POSITION_VERT_CENTER:
153
			case BACKGROUND_POSITION_VERT_TOP:
154
			case BACKGROUND_POSITION_VERT_BOTTOM:
155
				break;
156
			case BACKGROUND_POSITION_VERT_SET:
157
				value[0] = BACKGROUND_POSITION_HORZ_SET;
158
				break;
159
			}
160
 
161
			value[1] = BACKGROUND_POSITION_VERT_CENTER;
162
		} else if (value[0] != BACKGROUND_POSITION_VERT_SET &&
163
				value[1] != BACKGROUND_POSITION_VERT_SET) {
164
			/* Two keywords. Verify the axes differ */
165
			if (((value[0] & 0xf) != 0 && (value[1] & 0xf) != 0) ||
166
					((value[0] & 0xf0) != 0 &&
167
						(value[1] & 0xf0) != 0)) {
168
				*ctx = orig_ctx;
169
				return CSS_INVALID;
170
			}
171
		} else {
172
			/* One or two non-keywords. First is horizontal */
173
			if (value[0] == BACKGROUND_POSITION_VERT_SET)
174
				value[0] = BACKGROUND_POSITION_HORZ_SET;
175
 
176
			/* Verify the axes differ */
177
			if (((value[0] & 0xf) != 0 && (value[1] & 0xf) != 0) ||
178
					((value[0] & 0xf0) != 0 &&
179
						(value[1] & 0xf0) != 0)) {
180
				*ctx = orig_ctx;
181
				return CSS_INVALID;
182
			}
183
		}
184
	}
185
 
186
	error = css__stylesheet_style_appendOPV(result,
187
					       CSS_PROP_BACKGROUND_POSITION,
188
					       flags,
189
					       value[0] | value[1]);
190
	if (error != CSS_OK) {
191
		*ctx = orig_ctx;
192
		return error;
193
	}
194
 
195
	if ((flags & FLAG_INHERIT) == false) {
196
		if (value[0] == BACKGROUND_POSITION_HORZ_SET) {
197
			css__stylesheet_style_append(result, length[0]);
198
			css__stylesheet_style_append(result, unit[0]);
199
		}
200
		if (value[1] == BACKGROUND_POSITION_VERT_SET) {
201
			css__stylesheet_style_append(result, length[1]);
202
			css__stylesheet_style_append(result, unit[1]);
203
		}
204
	}
205
 
206
	return CSS_OK;
207
}