1 | #ifndef LH_CSS_SELECTOR_H |
2 | #define LH_CSS_SELECTOR_H |
3 | |
4 | #include "style.h" |
5 | #include "media_query.h" |
6 | |
7 | namespace litehtml |
8 | { |
9 | ////////////////////////////////////////////////////////////////////////// |
10 | |
11 | struct selector_specificity |
12 | { |
13 | int a; |
14 | int b; |
15 | int c; |
16 | int d; |
17 | |
18 | explicit selector_specificity(int va = 0, int vb = 0, int vc = 0, int vd = 0) |
19 | { |
20 | a = va; |
21 | b = vb; |
22 | c = vc; |
23 | d = vd; |
24 | } |
25 | |
26 | void operator += (const selector_specificity& val) |
27 | { |
28 | a += val.a; |
29 | b += val.b; |
30 | c += val.c; |
31 | d += val.d; |
32 | } |
33 | |
34 | bool operator==(const selector_specificity& val) const |
35 | { |
36 | if(a == val.a && b == val.b && c == val.c && d == val.d) |
37 | { |
38 | return true; |
39 | } |
40 | return false; |
41 | } |
42 | |
43 | bool operator!=(const selector_specificity& val) const |
44 | { |
45 | if(a != val.a || b != val.b || c != val.c || d != val.d) |
46 | { |
47 | return true; |
48 | } |
49 | return false; |
50 | } |
51 | |
52 | bool operator > (const selector_specificity& val) const |
53 | { |
54 | if(a > val.a) |
55 | { |
56 | return true; |
57 | } else if(a < val.a) |
58 | { |
59 | return false; |
60 | } else |
61 | { |
62 | if(b > val.b) |
63 | { |
64 | return true; |
65 | } else if(b < val.b) |
66 | { |
67 | return false; |
68 | } else |
69 | { |
70 | if(c > val.c) |
71 | { |
72 | return true; |
73 | } else if(c < val.c) |
74 | { |
75 | return false; |
76 | } else |
77 | { |
78 | if(d > val.d) |
79 | { |
80 | return true; |
81 | } else if(d < val.d) |
82 | { |
83 | return false; |
84 | } |
85 | } |
86 | } |
87 | } |
88 | return false; |
89 | } |
90 | |
91 | bool operator >= (const selector_specificity& val) const |
92 | { |
93 | if((*this) == val) return true; |
94 | if((*this) > val) return true; |
95 | return false; |
96 | } |
97 | |
98 | bool operator <= (const selector_specificity& val) const |
99 | { |
100 | if((*this) > val) |
101 | { |
102 | return false; |
103 | } |
104 | return true; |
105 | } |
106 | |
107 | bool operator < (const selector_specificity& val) const |
108 | { |
109 | if((*this) <= val && (*this) != val) |
110 | { |
111 | return true; |
112 | } |
113 | return false; |
114 | } |
115 | |
116 | }; |
117 | |
118 | ////////////////////////////////////////////////////////////////////////// |
119 | |
120 | enum attr_select_condition |
121 | { |
122 | select_exists, |
123 | select_equal, |
124 | select_contain_str, |
125 | select_start_str, |
126 | select_end_str, |
127 | select_pseudo_class, |
128 | select_pseudo_element, |
129 | }; |
130 | |
131 | ////////////////////////////////////////////////////////////////////////// |
132 | |
133 | struct css_attribute_selector |
134 | { |
135 | typedef std::vector<css_attribute_selector> vector; |
136 | |
137 | tstring attribute; |
138 | tstring val; |
139 | string_vector class_val; |
140 | attr_select_condition condition; |
141 | |
142 | css_attribute_selector() |
143 | { |
144 | condition = select_exists; |
145 | } |
146 | }; |
147 | |
148 | ////////////////////////////////////////////////////////////////////////// |
149 | |
150 | class css_element_selector |
151 | { |
152 | public: |
153 | tstring m_tag; |
154 | css_attribute_selector::vector m_attrs; |
155 | public: |
156 | |
157 | void parse(const tstring& txt); |
158 | }; |
159 | |
160 | ////////////////////////////////////////////////////////////////////////// |
161 | |
162 | enum css_combinator |
163 | { |
164 | combinator_descendant, |
165 | combinator_child, |
166 | combinator_adjacent_sibling, |
167 | combinator_general_sibling |
168 | }; |
169 | |
170 | ////////////////////////////////////////////////////////////////////////// |
171 | |
172 | class css_selector |
173 | { |
174 | public: |
175 | typedef std::shared_ptr<css_selector> ptr; |
176 | typedef std::vector<css_selector::ptr> vector; |
177 | public: |
178 | selector_specificity m_specificity; |
179 | css_element_selector m_right; |
180 | css_selector::ptr m_left; |
181 | css_combinator m_combinator; |
182 | tstring m_style; |
183 | int m_order; |
184 | media_query_list::ptr m_media_query; |
185 | tstring m_baseurl; |
186 | public: |
187 | explicit css_selector(const media_query_list::ptr& media, const tstring& baseurl) |
188 | { |
189 | m_media_query = media; |
190 | m_baseurl = baseurl; |
191 | m_combinator = combinator_descendant; |
192 | m_order = 0; |
193 | } |
194 | |
195 | ~css_selector() = default; |
196 | |
197 | css_selector(const css_selector& val) |
198 | { |
199 | m_right = val.m_right; |
200 | if(val.m_left) |
201 | { |
202 | m_left = std::make_shared<css_selector>(args&: *val.m_left); |
203 | } else |
204 | { |
205 | m_left = nullptr; |
206 | } |
207 | m_combinator = val.m_combinator; |
208 | m_specificity = val.m_specificity; |
209 | m_order = val.m_order; |
210 | m_media_query = val.m_media_query; |
211 | } |
212 | |
213 | bool parse(const tstring& text); |
214 | void calc_specificity(); |
215 | bool is_media_valid() const; |
216 | void add_media_to_doc(document* doc) const; |
217 | }; |
218 | |
219 | inline bool css_selector::is_media_valid() const |
220 | { |
221 | if(!m_media_query) |
222 | { |
223 | return true; |
224 | } |
225 | return m_media_query->is_used(); |
226 | } |
227 | |
228 | |
229 | ////////////////////////////////////////////////////////////////////////// |
230 | |
231 | inline bool operator > (const css_selector& v1, const css_selector& v2) |
232 | { |
233 | if(v1.m_specificity == v2.m_specificity) |
234 | { |
235 | return (v1.m_order > v2.m_order); |
236 | } |
237 | return (v1.m_specificity > v2.m_specificity); |
238 | } |
239 | |
240 | inline bool operator < (const css_selector& v1, const css_selector& v2) |
241 | { |
242 | if(v1.m_specificity == v2.m_specificity) |
243 | { |
244 | return (v1.m_order < v2.m_order); |
245 | } |
246 | return (v1.m_specificity < v2.m_specificity); |
247 | } |
248 | |
249 | inline bool operator >(const css_selector::ptr& v1, const css_selector::ptr& v2) |
250 | { |
251 | return (*v1 > *v2); |
252 | } |
253 | |
254 | inline bool operator < (const css_selector::ptr& v1, const css_selector::ptr& v2) |
255 | { |
256 | return (*v1 < *v2); |
257 | } |
258 | |
259 | ////////////////////////////////////////////////////////////////////////// |
260 | |
261 | class used_selector |
262 | { |
263 | public: |
264 | typedef std::unique_ptr<used_selector> ptr; |
265 | typedef std::vector<used_selector::ptr> vector; |
266 | |
267 | css_selector::ptr m_selector; |
268 | bool m_used; |
269 | |
270 | used_selector(const css_selector::ptr& selector, bool used) |
271 | { |
272 | m_used = used; |
273 | m_selector = selector; |
274 | } |
275 | }; |
276 | } |
277 | |
278 | #endif // LH_CSS_SELECTOR_H |
279 | |