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 "bytecode/bytecode.h"
9 #include "bytecode/opcodes.h"
10 #include "select/propset.h"
11 #include "select/propget.h"
12 #include "utils/utils.h"
13
14 #include "select/properties/properties.h"
15 #include "select/properties/helpers.h"
16
css__cascade_content(uint32_t opv,css_style * style,css_select_state * state)17 css_error css__cascade_content(uint32_t opv, css_style *style,
18 css_select_state *state)
19 {
20 uint16_t value = CSS_CONTENT_INHERIT;
21 css_computed_content_item *content = NULL;
22 uint32_t n_contents = 0;
23
24 if (isInherit(opv) == false) {
25 uint32_t v = getValue(opv);
26
27 if (v == CONTENT_NORMAL) {
28 value = CSS_CONTENT_NORMAL;
29 } else if (v == CONTENT_NONE) {
30 value = CSS_CONTENT_NONE;
31 } else {
32 value = CSS_CONTENT_SET;
33
34 while (v != CONTENT_NORMAL) {
35 lwc_string *he;
36 css_computed_content_item *temp;
37
38 css__stylesheet_string_get(style->sheet,
39 *((css_code_t *) style->bytecode), &he);
40
41 temp = realloc(content,
42 (n_contents + 1) *
43 sizeof(css_computed_content_item));
44 if (temp == NULL) {
45 if (content != NULL) {
46 free(content);
47 }
48 return CSS_NOMEM;
49 }
50
51 content = temp;
52 memset(content + n_contents, 0, sizeof(css_computed_content_item));
53
54 switch (v & 0xff) {
55 case CONTENT_COUNTER:
56 advance_bytecode(style, sizeof(css_code_t));
57
58 content[n_contents].type =
59 CSS_COMPUTED_CONTENT_COUNTER;
60 content[n_contents].data.counter.name = he;
61 content[n_contents].data.counter.style = v >> CONTENT_COUNTER_STYLE_SHIFT;
62 break;
63 case CONTENT_COUNTERS:
64 {
65 lwc_string *sep;
66
67 advance_bytecode(style, sizeof(css_code_t));
68
69 css__stylesheet_string_get(style->sheet, *((css_code_t *) style->bytecode), &sep);
70 advance_bytecode(style, sizeof(css_code_t));
71
72 content[n_contents].type =
73 CSS_COMPUTED_CONTENT_COUNTERS;
74 content[n_contents].data.counters.name = he;
75 content[n_contents].data.counters.sep = sep;
76 content[n_contents].data.counters.style = v >> CONTENT_COUNTERS_STYLE_SHIFT;
77 }
78 break;
79 case CONTENT_URI:
80 advance_bytecode(style, sizeof(css_code_t));
81
82 content[n_contents].type =
83 CSS_COMPUTED_CONTENT_URI;
84 content[n_contents].data.uri = he;
85 break;
86 case CONTENT_ATTR:
87 advance_bytecode(style, sizeof(css_code_t));
88
89 content[n_contents].type =
90 CSS_COMPUTED_CONTENT_ATTR;
91 content[n_contents].data.attr = he;
92 break;
93 case CONTENT_STRING:
94 advance_bytecode(style, sizeof(css_code_t));
95
96 content[n_contents].type =
97 CSS_COMPUTED_CONTENT_STRING;
98 content[n_contents].data.string = he;
99 break;
100 case CONTENT_OPEN_QUOTE:
101 content[n_contents].type =
102 CSS_COMPUTED_CONTENT_OPEN_QUOTE;
103 break;
104 case CONTENT_CLOSE_QUOTE:
105 content[n_contents].type =
106 CSS_COMPUTED_CONTENT_CLOSE_QUOTE;
107 break;
108 case CONTENT_NO_OPEN_QUOTE:
109 content[n_contents].type =
110 CSS_COMPUTED_CONTENT_NO_OPEN_QUOTE;
111 break;
112 case CONTENT_NO_CLOSE_QUOTE:
113 content[n_contents].type =
114 CSS_COMPUTED_CONTENT_NO_CLOSE_QUOTE;
115 break;
116 }
117
118 n_contents++;
119
120 v = *((uint32_t *) style->bytecode);
121 advance_bytecode(style, sizeof(v));
122 }
123 }
124 }
125
126 /* If we have some content, terminate the array with a blank entry */
127 if (n_contents > 0) {
128 css_computed_content_item *temp;
129
130 temp = realloc(content, (n_contents + 1) *
131 sizeof(css_computed_content_item));
132 if (temp == NULL) {
133 free(content);
134 return CSS_NOMEM;
135 }
136
137 content = temp;
138
139 content[n_contents].type = CSS_COMPUTED_CONTENT_NONE;
140 }
141
142 if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
143 isInherit(opv))) {
144 css_error error;
145
146 error = set_content(state->computed, value, content);
147 if (error != CSS_OK && content != NULL)
148 free(content);
149
150 return error;
151 } else if (content != NULL) {
152 free(content);
153 }
154
155 return CSS_OK;
156 }
157
css__set_content_from_hint(const css_hint * hint,css_computed_style * style)158 css_error css__set_content_from_hint(const css_hint *hint,
159 css_computed_style *style)
160 {
161 css_computed_content_item *item;
162 css_error error;
163
164 error = set_content(style, hint->status, hint->data.content);
165
166 for (item = hint->data.content; item != NULL &&
167 item->type != CSS_COMPUTED_CONTENT_NONE;
168 item++) {
169 switch (item->type) {
170 case CSS_COMPUTED_CONTENT_STRING:
171 lwc_string_unref(item->data.string);
172 break;
173 case CSS_COMPUTED_CONTENT_URI:
174 lwc_string_unref(item->data.uri);
175 break;
176 case CSS_COMPUTED_CONTENT_COUNTER:
177 lwc_string_unref(item->data.counter.name);
178 break;
179 case CSS_COMPUTED_CONTENT_COUNTERS:
180 lwc_string_unref(item->data.counters.name);
181 lwc_string_unref(item->data.counters.sep);
182 break;
183 case CSS_COMPUTED_CONTENT_ATTR:
184 lwc_string_unref(item->data.attr);
185 break;
186 default:
187 break;
188 }
189 }
190
191 if (error != CSS_OK && hint->data.content != NULL)
192 free(hint->data.content);
193
194 return error;
195 }
196
css__initial_content(css_select_state * state)197 css_error css__initial_content(css_select_state *state)
198 {
199 return set_content(state->computed, CSS_CONTENT_NORMAL, NULL);
200 }
201
css__compose_content(const css_computed_style * parent,const css_computed_style * child,css_computed_style * result)202 css_error css__compose_content(const css_computed_style *parent,
203 const css_computed_style *child,
204 css_computed_style *result)
205 {
206 css_error error;
207 css_computed_content_item *copy = NULL;
208 const css_computed_content_item *items = NULL;
209 uint8_t type = get_content(child, &items);
210
211 if (type == CSS_CONTENT_INHERIT) {
212 type = get_content(parent, &items);
213 }
214
215 if (type == CSS_CONTENT_SET) {
216 size_t n_items = 0;
217 const css_computed_content_item *i;
218
219 for (i = items; i->type != CSS_COMPUTED_CONTENT_NONE;
220 i++)
221 n_items++;
222
223 copy = malloc((n_items + 1) *
224 sizeof(css_computed_content_item));
225 if (copy == NULL)
226 return CSS_NOMEM;
227
228 memcpy(copy, items, (n_items + 1) *
229 sizeof(css_computed_content_item));
230 }
231
232 error = set_content(result, type, copy);
233 if (error != CSS_OK && copy != NULL)
234 free(copy);
235
236 return error;
237 }
238