9litehtml::string_map litehtml::style::m_valid_values =
11 { _t(
"white-space"), white_space_strings }
14litehtml::style::style()
18litehtml::style::style(
const style& val )
20 m_properties = val.m_properties;
23litehtml::style::~style()
28void litehtml::style::parse(
const tchar_t* txt,
const tchar_t* baseurl )
30 std::vector<tstring> properties;
31 split_string(txt, properties, _t(
";"), _t(
""), _t(
"\"'"));
33 for(std::vector<tstring>::const_iterator i = properties.begin(); i != properties.end(); i++)
35 parse_property(*i, baseurl);
39void litehtml::style::parse_property(
const tstring& txt,
const tchar_t* baseurl )
41 tstring::size_type pos = txt.find_first_of(_t(
":"));
42 if(pos != tstring::npos)
44 tstring name = txt.substr(0, pos);
45 tstring val = txt.substr(pos + 1);
47 trim(name); lcase(name);
50 if(!name.empty() && !val.empty())
53 split_string(val, vals, _t(
"!"));
56 add_property(name.c_str(), val.c_str(), baseurl,
false);
57 }
else if(vals.size() > 1)
61 add_property(name.c_str(), vals[0].c_str(), baseurl, vals[1] == _t(
"important"));
69 for(props_map::const_iterator i = src.m_properties.begin(); i != src.m_properties.end(); i++)
71 add_parsed_property(i->first.c_str(), i->second.m_value.c_str(), i->second.m_important);
75void litehtml::style::add_property(
const tchar_t* name,
const tchar_t* val,
const tchar_t* baseurl,
bool important )
83 if( !t_strcmp(name, _t(
"background-image")))
85 add_parsed_property(name, val, important);
88 add_parsed_property(_t(
"background-image-baseurl"), baseurl, important);
93 if( !t_strcmp(name, _t(
"border-spacing")))
96 split_string(val, tokens, _t(
" "));
97 if(tokens.size() == 1)
99 add_parsed_property(_t(
"-litehtml-border-spacing-x"), tokens[0].c_str(), important);
100 add_parsed_property(_t(
"-litehtml-border-spacing-y"), tokens[0].c_str(), important);
101 }
else if(tokens.size() == 2)
103 add_parsed_property(_t(
"-litehtml-border-spacing-x"), tokens[0].c_str(), important);
104 add_parsed_property(_t(
"-litehtml-border-spacing-y"), tokens[1].c_str(), important);
110 if( !t_strcmp(name, _t(
"border")))
112 string_vector tokens;
113 split_string(val, tokens, _t(
" "), _t(
""), _t(
"("));
116 for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
118 idx = value_index(tok->c_str(), border_style_strings, -1);
121 add_property(_t(
"border-left-style"), tok->c_str(), baseurl, important);
122 add_property(_t(
"border-right-style"), tok->c_str(), baseurl, important);
123 add_property(_t(
"border-top-style"), tok->c_str(), baseurl, important);
124 add_property(_t(
"border-bottom-style"), tok->c_str(), baseurl, important);
127 if (t_isdigit((*tok)[0]) || (*tok)[0] == _t(
'.') ||
128 value_in_list((*tok), _t(
"thin;medium;thick")))
130 add_property(_t(
"border-left-width"), tok->c_str(), baseurl, important);
131 add_property(_t(
"border-right-width"), tok->c_str(), baseurl, important);
132 add_property(_t(
"border-top-width"), tok->c_str(), baseurl, important);
133 add_property(_t(
"border-bottom-width"), tok->c_str(), baseurl, important);
137 add_property(_t(
"border-left-color"), tok->c_str(), baseurl, important);
138 add_property(_t(
"border-right-color"), tok->c_str(), baseurl, important);
139 add_property(_t(
"border-top-color"), tok->c_str(), baseurl, important);
140 add_property(_t(
"border-bottom-color"), tok->c_str(), baseurl, important);
144 }
else if( !t_strcmp(name, _t(
"border-left")) ||
145 !t_strcmp(name, _t(
"border-right")) ||
146 !t_strcmp(name, _t(
"border-top")) ||
147 !t_strcmp(name, _t(
"border-bottom")) )
149 string_vector tokens;
150 split_string(val, tokens, _t(
" "), _t(
""), _t(
"("));
153 for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
155 idx = value_index(tok->c_str(), border_style_strings, -1);
160 add_property(str.c_str(), tok->c_str(), baseurl, important);
163 if(web_color::is_color(tok->c_str()))
167 add_property(str.c_str(), tok->c_str(), baseurl, important);
172 add_property(str.c_str(), tok->c_str(), baseurl, important);
179 if(!t_strcmp(name, _t(
"border-bottom-left-radius")))
181 string_vector tokens;
182 split_string(val, tokens, _t(
" "));
183 if(tokens.size() >= 2)
185 add_property(_t(
"border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
186 add_property(_t(
"border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
187 }
else if(tokens.size() == 1)
189 add_property(_t(
"border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
190 add_property(_t(
"border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);
193 }
else if(!t_strcmp(name, _t(
"border-bottom-right-radius")))
195 string_vector tokens;
196 split_string(val, tokens, _t(
" "));
197 if(tokens.size() >= 2)
199 add_property(_t(
"border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
200 add_property(_t(
"border-bottom-right-radius-y"), tokens[1].c_str(), baseurl, important);
201 }
else if(tokens.size() == 1)
203 add_property(_t(
"border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
204 add_property(_t(
"border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
207 }
else if(!t_strcmp(name, _t(
"border-top-right-radius")))
209 string_vector tokens;
210 split_string(val, tokens, _t(
" "));
211 if(tokens.size() >= 2)
213 add_property(_t(
"border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
214 add_property(_t(
"border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
215 }
else if(tokens.size() == 1)
217 add_property(_t(
"border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
218 add_property(_t(
"border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);
221 }
else if(!t_strcmp(name, _t(
"border-top-left-radius")))
223 string_vector tokens;
224 split_string(val, tokens, _t(
" "));
225 if(tokens.size() >= 2)
227 add_property(_t(
"border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
228 add_property(_t(
"border-top-left-radius-y"), tokens[1].c_str(), baseurl, important);
229 }
else if(tokens.size() == 1)
231 add_property(_t(
"border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
232 add_property(_t(
"border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
238 if(!t_strcmp(name, _t(
"border-radius")))
240 string_vector tokens;
241 split_string(val, tokens, _t(
"/"));
242 if(tokens.size() == 1)
244 add_property(_t(
"border-radius-x"), tokens[0].c_str(), baseurl, important);
245 add_property(_t(
"border-radius-y"), tokens[0].c_str(), baseurl, important);
246 }
else if(tokens.size() >= 2)
248 add_property(_t(
"border-radius-x"), tokens[0].c_str(), baseurl, important);
249 add_property(_t(
"border-radius-y"), tokens[1].c_str(), baseurl, important);
251 }
else if(!t_strcmp(name, _t(
"border-radius-x")))
253 string_vector tokens;
254 split_string(val, tokens, _t(
" "));
255 if(tokens.size() == 1)
257 add_property(_t(
"border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
258 add_property(_t(
"border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
259 add_property(_t(
"border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
260 add_property(_t(
"border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
261 }
else if(tokens.size() == 2)
263 add_property(_t(
"border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
264 add_property(_t(
"border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
265 add_property(_t(
"border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
266 add_property(_t(
"border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);
267 }
else if(tokens.size() == 3)
269 add_property(_t(
"border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
270 add_property(_t(
"border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
271 add_property(_t(
"border-bottom-right-radius-x"), tokens[2].c_str(), baseurl, important);
272 add_property(_t(
"border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);
273 }
else if(tokens.size() == 4)
275 add_property(_t(
"border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
276 add_property(_t(
"border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
277 add_property(_t(
"border-bottom-right-radius-x"), tokens[2].c_str(), baseurl, important);
278 add_property(_t(
"border-bottom-left-radius-x"), tokens[3].c_str(), baseurl, important);
280 }
else if(!t_strcmp(name, _t(
"border-radius-y")))
282 string_vector tokens;
283 split_string(val, tokens, _t(
" "));
284 if(tokens.size() == 1)
286 add_property(_t(
"border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
287 add_property(_t(
"border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);
288 add_property(_t(
"border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
289 add_property(_t(
"border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);
290 }
else if(tokens.size() == 2)
292 add_property(_t(
"border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
293 add_property(_t(
"border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
294 add_property(_t(
"border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
295 add_property(_t(
"border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
296 }
else if(tokens.size() == 3)
298 add_property(_t(
"border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
299 add_property(_t(
"border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
300 add_property(_t(
"border-bottom-right-radius-y"), tokens[2].c_str(), baseurl, important);
301 add_property(_t(
"border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
302 }
else if(tokens.size() == 4)
304 add_property(_t(
"border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
305 add_property(_t(
"border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
306 add_property(_t(
"border-bottom-right-radius-y"), tokens[2].c_str(), baseurl, important);
307 add_property(_t(
"border-bottom-left-radius-y"), tokens[3].c_str(), baseurl, important);
313 if(!t_strcmp(name, _t(
"list-style")))
315 add_parsed_property(_t(
"list-style-type"), _t(
"disc"), important);
316 add_parsed_property(_t(
"list-style-position"), _t(
"outside"), important);
317 add_parsed_property(_t(
"list-style-image"), _t(
""), important);
318 add_parsed_property(_t(
"list-style-image-baseurl"), _t(
""), important);
320 string_vector tokens;
321 split_string(val, tokens, _t(
" "), _t(
""), _t(
"("));
322 for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
324 int idx = value_index(tok->c_str(), list_style_type_strings, -1);
327 add_parsed_property(_t(
"list-style-type"), *tok, important);
330 idx = value_index(tok->c_str(), list_style_position_strings, -1);
333 add_parsed_property(_t(
"list-style-position"), *tok, important);
334 }
else if(!t_strncmp(val, _t(
"url"), 3))
336 add_parsed_property(_t(
"list-style-image"), *tok, important);
339 add_parsed_property(_t(
"list-style-image-baseurl"), baseurl, important);
347 if( !t_strcmp(name, _t(
"list-style-image")))
349 add_parsed_property(name, val, important);
352 add_parsed_property(_t(
"list-style-image-baseurl"), baseurl, important);
357 if(!t_strcmp(name, _t(
"background")))
359 parse_short_background(val, baseurl, important);
364 if(!t_strcmp(name, _t(
"margin")) || !t_strcmp(name, _t(
"padding")))
366 string_vector tokens;
367 split_string(val, tokens, _t(
" "));
368 if(tokens.size() >= 4)
370 add_parsed_property(tstring(name) + _t(
"-top"), tokens[0], important);
371 add_parsed_property(tstring(name) + _t(
"-right"), tokens[1], important);
372 add_parsed_property(tstring(name) + _t(
"-bottom"), tokens[2], important);
373 add_parsed_property(tstring(name) + _t(
"-left"), tokens[3], important);
374 }
else if(tokens.size() == 3)
376 add_parsed_property(tstring(name) + _t(
"-top"), tokens[0], important);
377 add_parsed_property(tstring(name) + _t(
"-right"), tokens[1], important);
378 add_parsed_property(tstring(name) + _t(
"-left"), tokens[1], important);
379 add_parsed_property(tstring(name) + _t(
"-bottom"), tokens[2], important);
380 }
else if(tokens.size() == 2)
382 add_parsed_property(tstring(name) + _t(
"-top"), tokens[0], important);
383 add_parsed_property(tstring(name) + _t(
"-bottom"), tokens[0], important);
384 add_parsed_property(tstring(name) + _t(
"-right"), tokens[1], important);
385 add_parsed_property(tstring(name) + _t(
"-left"), tokens[1], important);
386 }
else if(tokens.size() == 1)
388 add_parsed_property(tstring(name) + _t(
"-top"), tokens[0], important);
389 add_parsed_property(tstring(name) + _t(
"-bottom"), tokens[0], important);
390 add_parsed_property(tstring(name) + _t(
"-right"), tokens[0], important);
391 add_parsed_property(tstring(name) + _t(
"-left"), tokens[0], important);
397 if( !t_strcmp(name, _t(
"border-left")) ||
398 !t_strcmp(name, _t(
"border-right")) ||
399 !t_strcmp(name, _t(
"border-top")) ||
400 !t_strcmp(name, _t(
"border-bottom")))
402 parse_short_border(name, val, important);
406 if( !t_strcmp(name, _t(
"border-width")) ||
407 !t_strcmp(name, _t(
"border-style")) ||
408 !t_strcmp(name, _t(
"border-color")) )
410 string_vector nametokens;
411 split_string(name, nametokens, _t(
"-"));
413 string_vector tokens;
414 split_string(val, tokens, _t(
" "));
415 if(tokens.size() >= 4)
417 add_parsed_property(nametokens[0] + _t(
"-top-") + nametokens[1], tokens[0], important);
418 add_parsed_property(nametokens[0] + _t(
"-right-") + nametokens[1], tokens[1], important);
419 add_parsed_property(nametokens[0] + _t(
"-bottom-") + nametokens[1], tokens[2], important);
420 add_parsed_property(nametokens[0] + _t(
"-left-") + nametokens[1], tokens[3], important);
421 }
else if(tokens.size() == 3)
423 add_parsed_property(nametokens[0] + _t(
"-top-") + nametokens[1], tokens[0], important);
424 add_parsed_property(nametokens[0] + _t(
"-right-") + nametokens[1], tokens[1], important);
425 add_parsed_property(nametokens[0] + _t(
"-left-") + nametokens[1], tokens[1], important);
426 add_parsed_property(nametokens[0] + _t(
"-bottom-") + nametokens[1], tokens[2], important);
427 }
else if(tokens.size() == 2)
429 add_parsed_property(nametokens[0] + _t(
"-top-") + nametokens[1], tokens[0], important);
430 add_parsed_property(nametokens[0] + _t(
"-bottom-") + nametokens[1], tokens[0], important);
431 add_parsed_property(nametokens[0] + _t(
"-right-") + nametokens[1], tokens[1], important);
432 add_parsed_property(nametokens[0] + _t(
"-left-") + nametokens[1], tokens[1], important);
433 }
else if(tokens.size() == 1)
435 add_parsed_property(nametokens[0] + _t(
"-top-") + nametokens[1], tokens[0], important);
436 add_parsed_property(nametokens[0] + _t(
"-bottom-") + nametokens[1], tokens[0], important);
437 add_parsed_property(nametokens[0] + _t(
"-right-") + nametokens[1], tokens[0], important);
438 add_parsed_property(nametokens[0] + _t(
"-left-") + nametokens[1], tokens[0], important);
443 if(!t_strcmp(name, _t(
"font")))
445 parse_short_font(val, important);
448 add_parsed_property(name, val, important);
452void litehtml::style::parse_short_border(
const tstring& prefix,
const tstring& val,
bool important )
454 string_vector tokens;
455 split_string(val, tokens, _t(
" "), _t(
""), _t(
"("));
456 if(tokens.size() >= 3)
458 add_parsed_property(prefix + _t(
"-width"), tokens[0], important);
459 add_parsed_property(prefix + _t(
"-style"), tokens[1], important);
460 add_parsed_property(prefix + _t(
"-color"), tokens[2], important);
461 }
else if(tokens.size() == 2)
463 if(iswdigit(tokens[0][0]) || value_index(val.c_str(), border_width_strings) >= 0)
465 add_parsed_property(prefix + _t(
"-width"), tokens[0], important);
466 add_parsed_property(prefix + _t(
"-style"), tokens[1], important);
469 add_parsed_property(prefix + _t(
"-style"), tokens[0], important);
470 add_parsed_property(prefix + _t(
"-color"), tokens[1], important);
475void litehtml::style::parse_short_background(
const tstring& val,
const tchar_t* baseurl,
bool important )
477 add_parsed_property(_t(
"background-color"), _t(
"transparent"), important);
478 add_parsed_property(_t(
"background-image"), _t(
""), important);
479 add_parsed_property(_t(
"background-image-baseurl"), _t(
""), important);
480 add_parsed_property(_t(
"background-repeat"), _t(
"repeat"), important);
481 add_parsed_property(_t(
"background-origin"), _t(
"padding-box"), important);
482 add_parsed_property(_t(
"background-clip"), _t(
"border-box"), important);
483 add_parsed_property(_t(
"background-attachment"), _t(
"scroll"), important);
485 if(val == _t(
"none"))
490 string_vector tokens;
491 split_string(val, tokens, _t(
" "), _t(
""), _t(
"("));
492 bool origin_found =
false;
493 for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
495 if(tok->substr(0, 3) == _t(
"url"))
497 add_parsed_property(_t(
"background-image"), *tok, important);
500 add_parsed_property(_t(
"background-image-baseurl"), baseurl, important);
503 }
else if( value_in_list(tok->c_str(), background_repeat_strings) )
505 add_parsed_property(_t(
"background-repeat"), *tok, important);
506 }
else if( value_in_list(tok->c_str(), background_attachment_strings) )
508 add_parsed_property(_t(
"background-attachment"), *tok, important);
509 }
else if( value_in_list(tok->c_str(), background_box_strings) )
513 add_parsed_property(_t(
"background-origin"), *tok, important);
517 add_parsed_property(_t(
"background-clip"),*tok, important);
519 }
else if( value_in_list(tok->c_str(), _t(
"left;right;top;bottom;center")) ||
520 iswdigit((*tok)[0]) ||
521 (*tok)[0] == _t(
'-') ||
522 (*tok)[0] == _t(
'.') ||
523 (*tok)[0] == _t(
'+'))
525 if(m_properties.find(_t(
"background-position")) != m_properties.end())
527 m_properties[_t(
"background-position")].m_value = m_properties[_t(
"background-position")].m_value + _t(
" ") + *tok;
530 add_parsed_property(_t(
"background-position"), *tok, important);
532 }
else if (web_color::is_color(tok->c_str()))
534 add_parsed_property(_t(
"background-color"), *tok, important);
539void litehtml::style::parse_short_font(
const tstring& val,
bool important )
541 add_parsed_property(_t(
"font-style"), _t(
"normal"), important);
542 add_parsed_property(_t(
"font-variant"), _t(
"normal"), important);
543 add_parsed_property(_t(
"font-weight"), _t(
"normal"), important);
544 add_parsed_property(_t(
"font-size"), _t(
"medium"), important);
545 add_parsed_property(_t(
"line-height"), _t(
"normal"), important);
547 string_vector tokens;
548 split_string(val, tokens, _t(
" "), _t(
""), _t(
"\""));
551 bool was_normal =
false;
552 bool is_family =
false;
554 for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
556 idx = value_index(tok->c_str(), font_style_strings);
561 if(idx == 0 && !was_normal)
563 add_parsed_property(_t(
"font-weight"), *tok, important);
564 add_parsed_property(_t(
"font-variant"), *tok, important);
565 add_parsed_property(_t(
"font-style"), *tok, important);
568 add_parsed_property(_t(
"font-style"), *tok, important);
572 if(value_in_list(tok->c_str(), font_weight_strings))
574 add_parsed_property(_t(
"font-weight"), *tok, important);
577 if(value_in_list(tok->c_str(), font_variant_strings))
579 add_parsed_property(_t(
"font-variant"), *tok, important);
580 }
else if( iswdigit((*tok)[0]) )
583 split_string(*tok, szlh, _t(
"/"));
587 add_parsed_property(_t(
"font-size"), szlh[0], important);
588 }
else if(szlh.size() >= 2)
590 add_parsed_property(_t(
"font-size"), szlh[0], important);
591 add_parsed_property(_t(
"line-height"), szlh[1], important);
605 add_parsed_property(_t(
"font-family"), font_family, important);
608void litehtml::style::add_parsed_property(
const tstring& name,
const tstring& val,
bool important )
610 bool is_valid =
true;
611 string_map::iterator vals = m_valid_values.find(name);
612 if (vals != m_valid_values.end())
614 if (!value_in_list(val, vals->second))
622 props_map::iterator prop = m_properties.find(name);
623 if (prop != m_properties.end())
625 if (!prop->second.m_important || (important && prop->second.m_important))
627 prop->second.m_value = val;
628 prop->second.m_important = important;
633 m_properties[name] = property_value(val.c_str(), important);
638void litehtml::style::remove_property(
const tstring& name,
bool important )
640 props_map::iterator prop = m_properties.find(name);
641 if(prop != m_properties.end())
643 if( !prop->second.m_important || (important && prop->second.m_important) )
645 m_properties.erase(prop);