9 litehtml::string_map litehtml::style::m_valid_values =
11 { _t("white-space"), white_space_strings }
14 litehtml::style::style()
18 litehtml::style::style( const style& val )
20 m_properties = val.m_properties;
23 litehtml::style::~style()
28 void litehtml::style::parse( const tchar_t* txt, const tchar_t* baseurl )
30 std::vector<tstring> properties;
31 split_string(txt, properties, _t(";"));
33 for(std::vector<tstring>::const_iterator i = properties.begin(); i != properties.end(); i++)
35 parse_property(*i, baseurl);
39 void 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);
52 if(!name.empty() && !val.empty())
55 split_string(val, vals, _t("!"));
58 add_property(name.c_str(), val.c_str(), baseurl, false);
59 } else if(vals.size() > 1)
63 if(vals[1] == _t("important"))
65 add_property(name.c_str(), vals[0].c_str(), baseurl, true);
68 add_property(name.c_str(), vals[0].c_str(), baseurl, false);
75 void litehtml::style::combine( const litehtml::style& src )
77 for(props_map::const_iterator i = src.m_properties.begin(); i != src.m_properties.end(); i++)
79 add_parsed_property(i->first.c_str(), i->second.m_value.c_str(), i->second.m_important);
83 void litehtml::style::add_property( const tchar_t* name, const tchar_t* val, const tchar_t* baseurl, bool important )
90 // Add baseurl for background image
91 if( !t_strcmp(name, _t("background-image")))
93 add_parsed_property(name, val, important);
96 add_parsed_property(_t("background-image-baseurl"), baseurl, important);
100 // Parse border spacing properties
101 if( !t_strcmp(name, _t("border-spacing")))
103 string_vector tokens;
104 split_string(val, tokens, _t(" "));
105 if(tokens.size() == 1)
107 add_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), baseurl, important);
108 add_property(_t("-litehtml-border-spacing-y"), tokens[0].c_str(), baseurl, important);
109 } else if(tokens.size() == 2)
111 add_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), baseurl, important);
112 add_property(_t("-litehtml-border-spacing-y"), tokens[1].c_str(), baseurl, important);
116 // Parse borders shorthand properties
118 if( !t_strcmp(name, _t("border")))
120 string_vector tokens;
121 split_string(val, tokens, _t(" "), _t(""), _t("("));
124 for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
126 idx = value_index(tok->c_str(), border_style_strings, -1);
129 add_property(_t("border-left-style"), tok->c_str(), baseurl, important);
130 add_property(_t("border-right-style"), tok->c_str(), baseurl, important);
131 add_property(_t("border-top-style"), tok->c_str(), baseurl, important);
132 add_property(_t("border-bottom-style"), tok->c_str(), baseurl, important);
135 if (t_isdigit((*tok)[0]) || (*tok)[0] == _t('.') ||
136 value_in_list((*tok), _t("thin;medium;thick")))
138 add_property(_t("border-left-width"), tok->c_str(), baseurl, important);
139 add_property(_t("border-right-width"), tok->c_str(), baseurl, important);
140 add_property(_t("border-top-width"), tok->c_str(), baseurl, important);
141 add_property(_t("border-bottom-width"), tok->c_str(), baseurl, important);
145 add_property(_t("border-left-color"), tok->c_str(), baseurl, important);
146 add_property(_t("border-right-color"), tok->c_str(), baseurl, important);
147 add_property(_t("border-top-color"), tok->c_str(), baseurl, important);
148 add_property(_t("border-bottom-color"), tok->c_str(), baseurl, important);
152 } else if( !t_strcmp(name, _t("border-left")) ||
153 !t_strcmp(name, _t("border-right")) ||
154 !t_strcmp(name, _t("border-top")) ||
155 !t_strcmp(name, _t("border-bottom")) )
157 string_vector tokens;
158 split_string(val, tokens, _t(" "), _t(""), _t("("));
161 for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
163 idx = value_index(tok->c_str(), border_style_strings, -1);
168 add_property(str.c_str(), tok->c_str(), baseurl, important);
171 if(web_color::is_color(tok->c_str()))
175 add_property(str.c_str(), tok->c_str(), baseurl, important);
180 add_property(str.c_str(), tok->c_str(), baseurl, important);
186 // Parse border radius shorthand properties
187 if(!t_strcmp(name, _t("border-bottom-left-radius")))
189 string_vector tokens;
190 split_string(val, tokens, _t(" "));
191 if(tokens.size() >= 2)
193 add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
194 add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
195 } else if(tokens.size() == 1)
197 add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
198 add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);
201 } else if(!t_strcmp(name, _t("border-bottom-right-radius")))
203 string_vector tokens;
204 split_string(val, tokens, _t(" "));
205 if(tokens.size() >= 2)
207 add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
208 add_property(_t("border-bottom-right-radius-y"), tokens[1].c_str(), baseurl, important);
209 } else if(tokens.size() == 1)
211 add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
212 add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
215 } else if(!t_strcmp(name, _t("border-top-right-radius")))
217 string_vector tokens;
218 split_string(val, tokens, _t(" "));
219 if(tokens.size() >= 2)
221 add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
222 add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
223 } else if(tokens.size() == 1)
225 add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
226 add_property(_t("border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);
229 } else if(!t_strcmp(name, _t("border-top-left-radius")))
231 string_vector tokens;
232 split_string(val, tokens, _t(" "));
233 if(tokens.size() >= 2)
235 add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
236 add_property(_t("border-top-left-radius-y"), tokens[1].c_str(), baseurl, important);
237 } else if(tokens.size() == 1)
239 add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
240 add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
245 // Parse border-radius shorthand properties
246 if(!t_strcmp(name, _t("border-radius")))
248 string_vector tokens;
249 split_string(val, tokens, _t("/"));
250 if(tokens.size() == 1)
252 add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);
253 add_property(_t("border-radius-y"), tokens[0].c_str(), baseurl, important);
254 } else if(tokens.size() >= 2)
256 add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);
257 add_property(_t("border-radius-y"), tokens[1].c_str(), baseurl, important);
259 } else if(!t_strcmp(name, _t("border-radius-x")))
261 string_vector tokens;
262 split_string(val, tokens, _t(" "));
263 if(tokens.size() == 1)
265 add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
266 add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
267 add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
268 add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
269 } else if(tokens.size() == 2)
271 add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
272 add_property(_t("border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
273 add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
274 add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);
275 } else if(tokens.size() == 3)
277 add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
278 add_property(_t("border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
279 add_property(_t("border-bottom-right-radius-x"), tokens[2].c_str(), baseurl, important);
280 add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);
281 } else if(tokens.size() == 4)
283 add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
284 add_property(_t("border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
285 add_property(_t("border-bottom-right-radius-x"), tokens[2].c_str(), baseurl, important);
286 add_property(_t("border-bottom-left-radius-x"), tokens[3].c_str(), baseurl, important);
288 } else if(!t_strcmp(name, _t("border-radius-y")))
290 string_vector tokens;
291 split_string(val, tokens, _t(" "));
292 if(tokens.size() == 1)
294 add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
295 add_property(_t("border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);
296 add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
297 add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);
298 } else if(tokens.size() == 2)
300 add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
301 add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
302 add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
303 add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
304 } else if(tokens.size() == 3)
306 add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
307 add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
308 add_property(_t("border-bottom-right-radius-y"), tokens[2].c_str(), baseurl, important);
309 add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
310 } else if(tokens.size() == 4)
312 add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
313 add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
314 add_property(_t("border-bottom-right-radius-y"), tokens[2].c_str(), baseurl, important);
315 add_property(_t("border-bottom-left-radius-y"), tokens[3].c_str(), baseurl, important);
320 // Parse list-style shorthand properties
321 if(!t_strcmp(name, _t("list-style")))
323 add_parsed_property(_t("list-style-type"), _t("disc"), important);
324 add_parsed_property(_t("list-style-position"), _t("outside"), important);
325 add_parsed_property(_t("list-style-image"), _t(""), important);
326 add_parsed_property(_t("list-style-image-baseurl"), _t(""), important);
328 string_vector tokens;
329 split_string(val, tokens, _t(" "), _t(""), _t("("));
330 for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
332 int idx = value_index(tok->c_str(), list_style_type_strings, -1);
335 add_parsed_property(_t("list-style-type"), *tok, important);
338 idx = value_index(tok->c_str(), list_style_position_strings, -1);
341 add_parsed_property(_t("list-style-position"), *tok, important);
342 } else if(!t_strncmp(val, _t("url"), 3))
344 add_parsed_property(_t("list-style-image"), *tok, important);
347 add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);
354 // Add baseurl for background image
355 if( !t_strcmp(name, _t("list-style-image")))
357 add_parsed_property(name, val, important);
360 add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);
364 // Parse background shorthand properties
365 if(!t_strcmp(name, _t("background")))
367 parse_short_background(val, baseurl, important);
371 // Parse margin and padding shorthand properties
372 if(!t_strcmp(name, _t("margin")) || !t_strcmp(name, _t("padding")))
374 string_vector tokens;
375 split_string(val, tokens, _t(" "));
376 if(tokens.size() >= 4)
378 add_parsed_property(tstring(name) + _t("-top"), tokens[0], important);
379 add_parsed_property(tstring(name) + _t("-right"), tokens[1], important);
380 add_parsed_property(tstring(name) + _t("-bottom"), tokens[2], important);
381 add_parsed_property(tstring(name) + _t("-left"), tokens[3], important);
382 } else if(tokens.size() == 3)
384 add_parsed_property(tstring(name) + _t("-top"), tokens[0], important);
385 add_parsed_property(tstring(name) + _t("-right"), tokens[1], important);
386 add_parsed_property(tstring(name) + _t("-left"), tokens[1], important);
387 add_parsed_property(tstring(name) + _t("-bottom"), tokens[2], important);
388 } else if(tokens.size() == 2)
390 add_parsed_property(tstring(name) + _t("-top"), tokens[0], important);
391 add_parsed_property(tstring(name) + _t("-bottom"), tokens[0], important);
392 add_parsed_property(tstring(name) + _t("-right"), tokens[1], important);
393 add_parsed_property(tstring(name) + _t("-left"), tokens[1], important);
394 } else if(tokens.size() == 1)
396 add_parsed_property(tstring(name) + _t("-top"), tokens[0], important);
397 add_parsed_property(tstring(name) + _t("-bottom"), tokens[0], important);
398 add_parsed_property(tstring(name) + _t("-right"), tokens[0], important);
399 add_parsed_property(tstring(name) + _t("-left"), tokens[0], important);
404 // Parse border-* shorthand properties
405 if( !t_strcmp(name, _t("border-left")) ||
406 !t_strcmp(name, _t("border-right")) ||
407 !t_strcmp(name, _t("border-top")) ||
408 !t_strcmp(name, _t("border-bottom")))
410 parse_short_border(name, val, important);
413 // Parse border-width/style/color shorthand properties
414 if( !t_strcmp(name, _t("border-width")) ||
415 !t_strcmp(name, _t("border-style")) ||
416 !t_strcmp(name, _t("border-color")) )
418 string_vector nametokens;
419 split_string(name, nametokens, _t("-"));
421 string_vector tokens;
422 split_string(val, tokens, _t(" "));
423 if(tokens.size() >= 4)
425 add_parsed_property(nametokens[0] + _t("-top-") + nametokens[1], tokens[0], important);
426 add_parsed_property(nametokens[0] + _t("-right-") + nametokens[1], tokens[1], important);
427 add_parsed_property(nametokens[0] + _t("-bottom-") + nametokens[1], tokens[2], important);
428 add_parsed_property(nametokens[0] + _t("-left-") + nametokens[1], tokens[3], important);
429 } else if(tokens.size() == 3)
431 add_parsed_property(nametokens[0] + _t("-top-") + nametokens[1], tokens[0], important);
432 add_parsed_property(nametokens[0] + _t("-right-") + nametokens[1], tokens[1], important);
433 add_parsed_property(nametokens[0] + _t("-left-") + nametokens[1], tokens[1], important);
434 add_parsed_property(nametokens[0] + _t("-bottom-") + nametokens[1], tokens[2], important);
435 } else if(tokens.size() == 2)
437 add_parsed_property(nametokens[0] + _t("-top-") + nametokens[1], tokens[0], important);
438 add_parsed_property(nametokens[0] + _t("-bottom-") + nametokens[1], tokens[0], important);
439 add_parsed_property(nametokens[0] + _t("-right-") + nametokens[1], tokens[1], important);
440 add_parsed_property(nametokens[0] + _t("-left-") + nametokens[1], tokens[1], important);
441 } else if(tokens.size() == 1)
443 add_parsed_property(nametokens[0] + _t("-top-") + nametokens[1], tokens[0], important);
444 add_parsed_property(nametokens[0] + _t("-bottom-") + nametokens[1], tokens[0], important);
445 add_parsed_property(nametokens[0] + _t("-right-") + nametokens[1], tokens[0], important);
446 add_parsed_property(nametokens[0] + _t("-left-") + nametokens[1], tokens[0], important);
450 // Parse font shorthand properties
451 if(!t_strcmp(name, _t("font")))
453 parse_short_font(val, important);
456 add_parsed_property(name, val, important);
460 void litehtml::style::parse_short_border( const tstring& prefix, const tstring& val, bool important )
462 string_vector tokens;
463 split_string(val, tokens, _t(" "), _t(""), _t("("));
464 if(tokens.size() >= 3)
466 add_parsed_property(prefix + _t("-width"), tokens[0], important);
467 add_parsed_property(prefix + _t("-style"), tokens[1], important);
468 add_parsed_property(prefix + _t("-color"), tokens[2], important);
469 } else if(tokens.size() == 2)
471 if(iswdigit(tokens[0][0]) || value_index(val.c_str(), border_width_strings) >= 0)
473 add_parsed_property(prefix + _t("-width"), tokens[0], important);
474 add_parsed_property(prefix + _t("-style"), tokens[1], important);
477 add_parsed_property(prefix + _t("-style"), tokens[0], important);
478 add_parsed_property(prefix + _t("-color"), tokens[1], important);
483 void litehtml::style::parse_short_background( const tstring& val, const tchar_t* baseurl, bool important )
485 add_parsed_property(_t("background-color"), _t("transparent"), important);
486 add_parsed_property(_t("background-image"), _t(""), important);
487 add_parsed_property(_t("background-image-baseurl"), _t(""), important);
488 add_parsed_property(_t("background-repeat"), _t("repeat"), important);
489 add_parsed_property(_t("background-origin"), _t("padding-box"), important);
490 add_parsed_property(_t("background-clip"), _t("border-box"), important);
491 add_parsed_property(_t("background-attachment"), _t("scroll"), important);
493 if(val == _t("none"))
498 string_vector tokens;
499 split_string(val, tokens, _t(" "), _t(""), _t("("));
500 bool origin_found = false;
501 for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
503 if(tok->substr(0, 3) == _t("url"))
505 add_parsed_property(_t("background-image"), *tok, important);
508 add_parsed_property(_t("background-image-baseurl"), baseurl, important);
511 } else if( value_in_list(tok->c_str(), background_repeat_strings) )
513 add_parsed_property(_t("background-repeat"), *tok, important);
514 } else if( value_in_list(tok->c_str(), background_attachment_strings) )
516 add_parsed_property(_t("background-attachment"), *tok, important);
517 } else if( value_in_list(tok->c_str(), background_box_strings) )
521 add_parsed_property(_t("background-origin"), *tok, important);
525 add_parsed_property(_t("background-clip"),*tok, important);
527 } else if( value_in_list(tok->c_str(), _t("left;right;top;bottom;center")) ||
528 iswdigit((*tok)[0]) ||
529 (*tok)[0] == _t('-') ||
530 (*tok)[0] == _t('.') ||
531 (*tok)[0] == _t('+'))
533 if(m_properties.find(_t("background-position")) != m_properties.end())
535 m_properties[_t("background-position")].m_value = m_properties[_t("background-position")].m_value + _t(" ") + *tok;
538 add_parsed_property(_t("background-position"), *tok, important);
540 } else if (web_color::is_color(tok->c_str()))
542 add_parsed_property(_t("background-color"), *tok, important);
547 void litehtml::style::parse_short_font( const tstring& val, bool important )
549 add_parsed_property(_t("font-style"), _t("normal"), important);
550 add_parsed_property(_t("font-variant"), _t("normal"), important);
551 add_parsed_property(_t("font-weight"), _t("normal"), important);
552 add_parsed_property(_t("font-size"), _t("medium"), important);
553 add_parsed_property(_t("line-height"), _t("normal"), important);
555 string_vector tokens;
556 split_string(val, tokens, _t(" "), _t(""), _t("\""));
559 bool was_normal = false;
560 bool is_family = false;
562 for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
564 idx = value_index(tok->c_str(), font_style_strings);
569 if(idx == 0 && !was_normal)
571 add_parsed_property(_t("font-weight"), *tok, important);
572 add_parsed_property(_t("font-variant"), *tok, important);
573 add_parsed_property(_t("font-style"), *tok, important);
576 add_parsed_property(_t("font-style"), *tok, important);
580 if(value_in_list(tok->c_str(), font_weight_strings))
582 add_parsed_property(_t("font-weight"), *tok, important);
585 if(value_in_list(tok->c_str(), font_variant_strings))
587 add_parsed_property(_t("font-variant"), *tok, important);
588 } else if( iswdigit((*tok)[0]) )
591 split_string(*tok, szlh, _t("/"));
595 add_parsed_property(_t("font-size"), szlh[0], important);
596 } else if(szlh.size() >= 2)
598 add_parsed_property(_t("font-size"), szlh[0], important);
599 add_parsed_property(_t("line-height"), szlh[1], important);
613 add_parsed_property(_t("font-family"), font_family, important);
616 void litehtml::style::add_parsed_property( const tstring& name, const tstring& val, bool important )
618 bool is_valid = true;
619 string_map::iterator vals = m_valid_values.find(name);
620 if (vals != m_valid_values.end())
622 if (!value_in_list(val, vals->second))
630 props_map::iterator prop = m_properties.find(name);
631 if (prop != m_properties.end())
633 if (!prop->second.m_important || (important && prop->second.m_important))
635 prop->second.m_value = val;
636 prop->second.m_important = important;
641 m_properties[name] = property_value(val.c_str(), important);
646 void litehtml::style::remove_property( const tstring& name, bool important )
648 props_map::iterator prop = m_properties.find(name);
649 if(prop != m_properties.end())
651 if( !prop->second.m_important || (important && prop->second.m_important) )
653 m_properties.erase(prop);