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 <jmb@netsurf-browser.org>
6 */
7
8 #include <assert.h>
9 #include <string.h>
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 elevation
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 */
css__parse_elevation(css_language * c,const parserutils_vector * vector,int * ctx,css_style * result)30 css_error css__parse_elevation(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 = 0;
39 css_fixed length = 0;
40 uint32_t unit = 0;
41 bool match;
42
43 /* angle | IDENT(below, level, above, higher, lower, inherit) */
44 token = parserutils_vector_peek(vector, *ctx);
45 if (token == NULL) {
46 *ctx = orig_ctx;
47 return CSS_INVALID;
48 }
49
50 if (token->type == CSS_TOKEN_IDENT &&
51 (lwc_string_caseless_isequal(
52 token->idata, c->strings[INHERIT],
53 &match) == lwc_error_ok && match)) {
54 parserutils_vector_iterate(vector, ctx);
55 flags = FLAG_INHERIT;
56 } else if (token->type == CSS_TOKEN_IDENT &&
57 (lwc_string_caseless_isequal(
58 token->idata, c->strings[BELOW],
59 &match) == lwc_error_ok && match)) {
60 parserutils_vector_iterate(vector, ctx);
61 value = ELEVATION_BELOW;
62 } else if (token->type == CSS_TOKEN_IDENT &&
63 (lwc_string_caseless_isequal(
64 token->idata, c->strings[LEVEL],
65 &match) == lwc_error_ok && match)) {
66 parserutils_vector_iterate(vector, ctx);
67 value = ELEVATION_LEVEL;
68 } else if (token->type == CSS_TOKEN_IDENT &&
69 (lwc_string_caseless_isequal(
70 token->idata, c->strings[ABOVE],
71 &match) == lwc_error_ok && match)) {
72 parserutils_vector_iterate(vector, ctx);
73 value = ELEVATION_ABOVE;
74 } else if (token->type == CSS_TOKEN_IDENT &&
75 (lwc_string_caseless_isequal(
76 token->idata, c->strings[HIGHER],
77 &match) == lwc_error_ok && match)) {
78 parserutils_vector_iterate(vector, ctx);
79 value = ELEVATION_HIGHER;
80 } else if (token->type == CSS_TOKEN_IDENT &&
81 (lwc_string_caseless_isequal(
82 token->idata, c->strings[LOWER],
83 &match) == lwc_error_ok && match)) {
84 parserutils_vector_iterate(vector, ctx);
85 value = ELEVATION_LOWER;
86 } else {
87 error = css__parse_unit_specifier(c, vector, ctx, UNIT_DEG,
88 &length, &unit);
89 if (error != CSS_OK) {
90 *ctx = orig_ctx;
91 return error;
92 }
93
94 if ((unit & UNIT_ANGLE) == false) {
95 *ctx = orig_ctx;
96 return CSS_INVALID;
97 }
98
99 /* Valid angles lie between -90 and 90 degrees */
100 if (unit == UNIT_DEG) {
101 if (length < -F_90 || length > F_90) {
102 *ctx = orig_ctx;
103 return CSS_INVALID;
104 }
105 } else if (unit == UNIT_GRAD) {
106 if (length < -F_100 || length > F_100) {
107 *ctx = orig_ctx;
108 return CSS_INVALID;
109 }
110 } else if (unit == UNIT_RAD) {
111 if (length < -F_PI_2 || length > F_PI_2) {
112 *ctx = orig_ctx;
113 return CSS_INVALID;
114 }
115 }
116
117 value = ELEVATION_ANGLE;
118 }
119
120 error = css__stylesheet_style_appendOPV(result, CSS_PROP_ELEVATION, flags, value);
121 if (error != CSS_OK) {
122 *ctx = orig_ctx;
123 return error;
124 }
125
126 if (((flags & FLAG_INHERIT) == false) && (value == ELEVATION_ANGLE)) {
127 error = css__stylesheet_style_vappend(result, 2, length, unit);
128 if (error != CSS_OK) {
129 *ctx = orig_ctx;
130 return error;
131 }
132 }
133
134 return CSS_OK;
135 }
136