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 "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 | |||
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, *((css_code_t *) style->bytecode), &he); |
||
39 | |||
40 | temp = state->computed->alloc(content, |
||
41 | (n_contents + 1) * |
||
42 | sizeof(css_computed_content_item), |
||
43 | state->computed->pw); |
||
44 | if (temp == NULL) { |
||
45 | if (content != NULL) { |
||
46 | state->computed->alloc(content, |
||
47 | 0, state->computed->pw); |
||
48 | } |
||
49 | return CSS_NOMEM; |
||
50 | } |
||
51 | |||
52 | content = temp; |
||
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 = state->computed->alloc(content, |
||
131 | (n_contents + 1) * sizeof(css_computed_content_item), |
||
132 | state->computed->pw); |
||
133 | if (temp == NULL) { |
||
134 | state->computed->alloc(content, 0, state->computed->pw); |
||
135 | return CSS_NOMEM; |
||
136 | } |
||
137 | |||
138 | content = temp; |
||
139 | |||
140 | content[n_contents].type = CSS_COMPUTED_CONTENT_NONE; |
||
141 | } |
||
142 | |||
143 | if (css__outranks_existing(getOpcode(opv), isImportant(opv), state, |
||
144 | isInherit(opv))) { |
||
145 | css_error error; |
||
146 | |||
147 | error = set_content(state->computed, value, content); |
||
148 | if (error != CSS_OK && content != NULL) |
||
149 | state->computed->alloc(content, 0, state->computed->pw); |
||
150 | |||
151 | return error; |
||
152 | } else if (content != NULL) { |
||
153 | state->computed->alloc(content, 0, state->computed->pw); |
||
154 | } |
||
155 | |||
156 | return CSS_OK; |
||
157 | } |
||
158 | |||
159 | css_error css__set_content_from_hint(const css_hint *hint, |
||
160 | css_computed_style *style) |
||
161 | { |
||
162 | css_computed_content_item *item; |
||
163 | css_error error; |
||
164 | |||
165 | error = set_content(style, hint->status, hint->data.content); |
||
166 | |||
167 | for (item = hint->data.content; item != NULL && |
||
168 | item->type != CSS_COMPUTED_CONTENT_NONE; |
||
169 | item++) { |
||
170 | switch (item->type) { |
||
171 | case CSS_COMPUTED_CONTENT_STRING: |
||
172 | lwc_string_unref(item->data.string); |
||
173 | break; |
||
174 | case CSS_COMPUTED_CONTENT_URI: |
||
175 | lwc_string_unref(item->data.uri); |
||
176 | break; |
||
177 | case CSS_COMPUTED_CONTENT_COUNTER: |
||
178 | lwc_string_unref(item->data.counter.name); |
||
179 | break; |
||
180 | case CSS_COMPUTED_CONTENT_COUNTERS: |
||
181 | lwc_string_unref(item->data.counters.name); |
||
182 | lwc_string_unref(item->data.counters.sep); |
||
183 | break; |
||
184 | case CSS_COMPUTED_CONTENT_ATTR: |
||
185 | lwc_string_unref(item->data.attr); |
||
186 | break; |
||
187 | default: |
||
188 | break; |
||
189 | } |
||
190 | } |
||
191 | |||
192 | if (error != CSS_OK && hint->data.content != NULL) |
||
193 | style->alloc(hint->data.content, 0, style->pw); |
||
194 | |||
195 | return error; |
||
196 | } |
||
197 | |||
198 | css_error css__initial_content(css_select_state *state) |
||
199 | { |
||
200 | return set_content(state->computed, CSS_CONTENT_NORMAL, NULL); |
||
201 | } |
||
202 | |||
203 | css_error css__compose_content(const css_computed_style *parent, |
||
204 | const css_computed_style *child, |
||
205 | css_computed_style *result) |
||
206 | { |
||
207 | css_error error; |
||
208 | const css_computed_content_item *items = NULL; |
||
209 | uint8_t type = get_content(child, &items); |
||
210 | |||
211 | if ((child->uncommon == NULL && parent->uncommon != NULL) || |
||
212 | type == CSS_CONTENT_INHERIT || |
||
213 | (child->uncommon != NULL && result != child)) { |
||
214 | size_t n_items = 0; |
||
215 | css_computed_content_item *copy = NULL; |
||
216 | |||
217 | if ((child->uncommon == NULL && parent->uncommon != NULL) || |
||
218 | type == CSS_CONTENT_INHERIT) { |
||
219 | type = get_content(parent, &items); |
||
220 | } |
||
221 | |||
222 | if (type == CSS_CONTENT_SET) { |
||
223 | const css_computed_content_item *i; |
||
224 | |||
225 | for (i = items; i->type != CSS_COMPUTED_CONTENT_NONE; |
||
226 | i++) |
||
227 | n_items++; |
||
228 | |||
229 | copy = result->alloc(NULL, (n_items + 1) * |
||
230 | sizeof(css_computed_content_item), |
||
231 | result->pw); |
||
232 | if (copy == NULL) |
||
233 | return CSS_NOMEM; |
||
234 | |||
235 | memcpy(copy, items, (n_items + 1) * |
||
236 | sizeof(css_computed_content_item)); |
||
237 | } |
||
238 | |||
239 | error = set_content(result, type, copy); |
||
240 | if (error != CSS_OK && copy != NULL) |
||
241 | result->alloc(copy, 0, result->pw); |
||
242 | |||
243 | return error; |
||
244 | } |
||
245 | |||
246 | return CSS_OK; |
||
247 | } |
||
248 |