1 #include "html.h"
2 #include "style.h"
3 #include <functional>
4 #include <algorithm>
5 #ifndef WINCE
6 #include <locale>
7 #endif
8 
9 litehtml::string_map litehtml::style::m_valid_values =
10 {
11 	{ _t("white-space"), white_space_strings }
12 };
13 
style()14 litehtml::style::style()
15 {
16 }
17 
style(const style & val)18 litehtml::style::style( const style& val )
19 {
20 	m_properties = val.m_properties;
21 }
22 
~style()23 litehtml::style::~style()
24 {
25 
26 }
27 
parse(const tchar_t * txt,const tchar_t * baseurl)28 void litehtml::style::parse( const tchar_t* txt, const tchar_t* baseurl )
29 {
30 	std::vector<tstring> properties;
31 	split_string(txt, properties, _t(";"));
32 
33 	for(std::vector<tstring>::const_iterator i = properties.begin(); i != properties.end(); i++)
34 	{
35 		parse_property(*i, baseurl);
36 	}
37 }
38 
parse_property(const tstring & txt,const tchar_t * baseurl)39 void litehtml::style::parse_property( const tstring& txt, const tchar_t* baseurl )
40 {
41 	tstring::size_type pos = txt.find_first_of(_t(":"));
42 	if(pos != tstring::npos)
43 	{
44 		tstring name	= txt.substr(0, pos);
45 		tstring val	= txt.substr(pos + 1);
46 
47 		trim(name);
48 		trim(val);
49 
50 		lcase(name);
51 
52 		if(!name.empty() && !val.empty())
53 		{
54 			string_vector vals;
55 			split_string(val, vals, _t("!"));
56 			if(vals.size() == 1)
57 			{
58 				add_property(name.c_str(), val.c_str(), baseurl, false);
59 			} else if(vals.size() > 1)
60 			{
61 				trim(vals[0]);
62 				lcase(vals[1]);
63 				if(vals[1] == _t("important"))
64 				{
65 					add_property(name.c_str(), vals[0].c_str(), baseurl, true);
66 				} else
67 				{
68 					add_property(name.c_str(), vals[0].c_str(), baseurl, false);
69 				}
70 			}
71 		}
72 	}
73 }
74 
combine(const litehtml::style & src)75 void litehtml::style::combine( const litehtml::style& src )
76 {
77 	for(props_map::const_iterator i = src.m_properties.begin(); i != src.m_properties.end(); i++)
78 	{
79 		add_parsed_property(i->first.c_str(), i->second.m_value.c_str(), i->second.m_important);
80 	}
81 }
82 
add_property(const tchar_t * name,const tchar_t * val,const tchar_t * baseurl,bool important)83 void litehtml::style::add_property( const tchar_t* name, const tchar_t* val, const tchar_t* baseurl, bool important )
84 {
85 	if(!name || !val)
86 	{
87 		return;
88 	}
89 
90 	// Add baseurl for background image
91 	if(	!t_strcmp(name, _t("background-image")))
92 	{
93 		add_parsed_property(name, val, important);
94 		if(baseurl)
95 		{
96 			add_parsed_property(_t("background-image-baseurl"), baseurl, important);
97 		}
98 	} else
99 
100 	// Parse border spacing properties
101 	if(	!t_strcmp(name, _t("border-spacing")))
102 	{
103 		string_vector tokens;
104 		split_string(val, tokens, _t(" "));
105 		if(tokens.size() == 1)
106 		{
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)
110 		{
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);
113 		}
114 	} else
115 
116 	// Parse borders shorthand properties
117 
118 	if(	!t_strcmp(name, _t("border")))
119 	{
120 		string_vector tokens;
121 		split_string(val, tokens, _t(" "), _t(""), _t("("));
122 		int idx;
123 		tstring str;
124 		for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
125 		{
126 			idx = value_index(tok->c_str(), border_style_strings, -1);
127 			if(idx >= 0)
128 			{
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);
133 			} else
134 			{
135 				if (t_isdigit((*tok)[0]) || (*tok)[0] == _t('.') ||
136 					value_in_list((*tok), _t("thin;medium;thick")))
137 				{
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);
142 				}
143 				else
144 				{
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);
149 				}
150 			}
151 		}
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")) )
156 	{
157 		string_vector tokens;
158 		split_string(val, tokens, _t(" "), _t(""), _t("("));
159 		int idx;
160 		tstring str;
161 		for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
162 		{
163 			idx = value_index(tok->c_str(), border_style_strings, -1);
164 			if(idx >= 0)
165 			{
166 				str = name;
167 				str += _t("-style");
168 				add_property(str.c_str(), tok->c_str(), baseurl, important);
169 			} else
170 			{
171 				if(web_color::is_color(tok->c_str()))
172 				{
173 					str = name;
174 					str += _t("-color");
175 					add_property(str.c_str(), tok->c_str(), baseurl, important);
176 				} else
177 				{
178 					str = name;
179 					str += _t("-width");
180 					add_property(str.c_str(), tok->c_str(), baseurl, important);
181 				}
182 			}
183 		}
184 	} else
185 
186 	// Parse border radius shorthand properties
187 	if(!t_strcmp(name, _t("border-bottom-left-radius")))
188 	{
189 		string_vector tokens;
190 		split_string(val, tokens, _t(" "));
191 		if(tokens.size() >= 2)
192 		{
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)
196 		{
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);
199 		}
200 
201 	} else if(!t_strcmp(name, _t("border-bottom-right-radius")))
202 	{
203 		string_vector tokens;
204 		split_string(val, tokens, _t(" "));
205 		if(tokens.size() >= 2)
206 		{
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)
210 		{
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);
213 		}
214 
215 	} else if(!t_strcmp(name, _t("border-top-right-radius")))
216 	{
217 		string_vector tokens;
218 		split_string(val, tokens, _t(" "));
219 		if(tokens.size() >= 2)
220 		{
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)
224 		{
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);
227 		}
228 
229 	} else if(!t_strcmp(name, _t("border-top-left-radius")))
230 	{
231 		string_vector tokens;
232 		split_string(val, tokens, _t(" "));
233 		if(tokens.size() >= 2)
234 		{
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)
238 		{
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);
241 		}
242 
243 	} else
244 
245 	// Parse border-radius shorthand properties
246 	if(!t_strcmp(name, _t("border-radius")))
247 	{
248 		string_vector tokens;
249 		split_string(val, tokens, _t("/"));
250 		if(tokens.size() == 1)
251 		{
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)
255 		{
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);
258 		}
259 	} else if(!t_strcmp(name, _t("border-radius-x")))
260 	{
261 		string_vector tokens;
262 		split_string(val, tokens, _t(" "));
263 		if(tokens.size() == 1)
264 		{
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)
270 		{
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)
276 		{
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)
282 		{
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);
287 		}
288 	} else if(!t_strcmp(name, _t("border-radius-y")))
289 	{
290 		string_vector tokens;
291 		split_string(val, tokens, _t(" "));
292 		if(tokens.size() == 1)
293 		{
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)
299 		{
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)
305 		{
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)
311 		{
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);
316 		}
317 	}
318 
319 
320 	// Parse list-style shorthand properties
321 	if(!t_strcmp(name, _t("list-style")))
322 	{
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);
327 
328 		string_vector tokens;
329 		split_string(val, tokens, _t(" "), _t(""), _t("("));
330 		for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
331 		{
332 			int idx = value_index(tok->c_str(), list_style_type_strings, -1);
333 			if(idx >= 0)
334 			{
335 				add_parsed_property(_t("list-style-type"), *tok, important);
336 			} else
337 			{
338 				idx = value_index(tok->c_str(), list_style_position_strings, -1);
339 				if(idx >= 0)
340 				{
341 					add_parsed_property(_t("list-style-position"), *tok, important);
342 				} else if(!t_strncmp(val, _t("url"), 3))
343 				{
344 					add_parsed_property(_t("list-style-image"), *tok, important);
345 					if(baseurl)
346 					{
347 						add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);
348 					}
349 				}
350 			}
351 		}
352 	} else
353 
354 	// Add baseurl for background image
355 	if(	!t_strcmp(name, _t("list-style-image")))
356 	{
357 		add_parsed_property(name, val, important);
358 		if(baseurl)
359 		{
360 			add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);
361 		}
362 	} else
363 
364 	// Parse background shorthand properties
365 	if(!t_strcmp(name, _t("background")))
366 	{
367 		parse_short_background(val, baseurl, important);
368 
369 	} else
370 
371 	// Parse margin and padding shorthand properties
372 	if(!t_strcmp(name, _t("margin")) || !t_strcmp(name, _t("padding")))
373 	{
374 		string_vector tokens;
375 		split_string(val, tokens, _t(" "));
376 		if(tokens.size() >= 4)
377 		{
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)
383 		{
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)
389 		{
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)
395 		{
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);
400 		}
401 	} else
402 
403 
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")))
409 	{
410 		parse_short_border(name, val, important);
411 	} else
412 
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")) )
417 	{
418 		string_vector nametokens;
419 		split_string(name, nametokens, _t("-"));
420 
421 		string_vector tokens;
422 		split_string(val, tokens, _t(" "));
423 		if(tokens.size() >= 4)
424 		{
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)
430 		{
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)
436 		{
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)
442 		{
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);
447 		}
448 	} else
449 
450 	// Parse font shorthand properties
451 	if(!t_strcmp(name, _t("font")))
452 	{
453 		parse_short_font(val, important);
454 	} else
455 	{
456 		add_parsed_property(name, val, important);
457 	}
458 }
459 
parse_short_border(const tstring & prefix,const tstring & val,bool important)460 void litehtml::style::parse_short_border( const tstring& prefix, const tstring& val, bool important )
461 {
462 	string_vector tokens;
463 	split_string(val, tokens, _t(" "), _t(""), _t("("));
464 	if(tokens.size() >= 3)
465 	{
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)
470 	{
471 		if(iswdigit(tokens[0][0]) || value_index(val.c_str(), border_width_strings) >= 0)
472 		{
473 			add_parsed_property(prefix + _t("-width"),	tokens[0], important);
474 			add_parsed_property(prefix + _t("-style"),	tokens[1], important);
475 		} else
476 		{
477 			add_parsed_property(prefix + _t("-style"),	tokens[0], important);
478 			add_parsed_property(prefix + _t("-color"),	tokens[1], important);
479 		}
480 	}
481 }
482 
parse_short_background(const tstring & val,const tchar_t * baseurl,bool important)483 void litehtml::style::parse_short_background( const tstring& val, const tchar_t* baseurl, bool important )
484 {
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);
492 
493 	if(val == _t("none"))
494 	{
495 		return;
496 	}
497 
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++)
502 	{
503 		if(tok->substr(0, 3) == _t("url"))
504 		{
505 			add_parsed_property(_t("background-image"), *tok, important);
506 			if(baseurl)
507 			{
508 				add_parsed_property(_t("background-image-baseurl"), baseurl, important);
509 			}
510 
511 		} else if( value_in_list(tok->c_str(), background_repeat_strings) )
512 		{
513 			add_parsed_property(_t("background-repeat"), *tok, important);
514 		} else if( value_in_list(tok->c_str(), background_attachment_strings) )
515 		{
516 			add_parsed_property(_t("background-attachment"), *tok, important);
517 		} else if( value_in_list(tok->c_str(), background_box_strings) )
518 		{
519 			if(!origin_found)
520 			{
521 				add_parsed_property(_t("background-origin"), *tok, important);
522 				origin_found = true;
523 			} else
524 			{
525 				add_parsed_property(_t("background-clip"),*tok, important);
526 			}
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('+'))
532 		{
533 			if(m_properties.find(_t("background-position")) != m_properties.end())
534 			{
535 				m_properties[_t("background-position")].m_value = m_properties[_t("background-position")].m_value + _t(" ") + *tok;
536 			} else
537 			{
538 				add_parsed_property(_t("background-position"), *tok, important);
539 			}
540 		} else if (web_color::is_color(tok->c_str()))
541 		{
542 			add_parsed_property(_t("background-color"), *tok, important);
543 		}
544 	}
545 }
546 
parse_short_font(const tstring & val,bool important)547 void litehtml::style::parse_short_font( const tstring& val, bool important )
548 {
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);
554 
555 	string_vector tokens;
556 	split_string(val, tokens, _t(" "), _t(""), _t("\""));
557 
558 	int idx = 0;
559 	bool was_normal = false;
560 	bool is_family = false;
561 	tstring font_family;
562 	for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
563 	{
564 		idx = value_index(tok->c_str(), font_style_strings);
565 		if(!is_family)
566 		{
567 			if(idx >= 0)
568 			{
569 				if(idx == 0 && !was_normal)
570 				{
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);
574 				} else
575 				{
576 					add_parsed_property(_t("font-style"),		*tok, important);
577 				}
578 			} else
579 			{
580 				if(value_in_list(tok->c_str(), font_weight_strings))
581 				{
582 					add_parsed_property(_t("font-weight"),		*tok, important);
583 				} else
584 				{
585 					if(value_in_list(tok->c_str(), font_variant_strings))
586 					{
587 						add_parsed_property(_t("font-variant"),	*tok, important);
588 					} else if( iswdigit((*tok)[0]) )
589 					{
590 						string_vector szlh;
591 						split_string(*tok, szlh, _t("/"));
592 
593 						if(szlh.size() == 1)
594 						{
595 							add_parsed_property(_t("font-size"),	szlh[0], important);
596 						} else	if(szlh.size() >= 2)
597 						{
598 							add_parsed_property(_t("font-size"),	szlh[0], important);
599 							add_parsed_property(_t("line-height"),	szlh[1], important);
600 						}
601 					} else
602 					{
603 						is_family = true;
604 						font_family += *tok;
605 					}
606 				}
607 			}
608 		} else
609 		{
610 			font_family += *tok;
611 		}
612 	}
613 	add_parsed_property(_t("font-family"), font_family, important);
614 }
615 
add_parsed_property(const tstring & name,const tstring & val,bool important)616 void litehtml::style::add_parsed_property( const tstring& name, const tstring& val, bool important )
617 {
618 	bool is_valid = true;
619 	string_map::iterator vals = m_valid_values.find(name);
620 	if (vals != m_valid_values.end())
621 	{
622 		if (!value_in_list(val, vals->second))
623 		{
624 			is_valid = false;
625 		}
626 	}
627 
628 	if (is_valid)
629 	{
630 		props_map::iterator prop = m_properties.find(name);
631 		if (prop != m_properties.end())
632 		{
633 			if (!prop->second.m_important || (important && prop->second.m_important))
634 			{
635 				prop->second.m_value = val;
636 				prop->second.m_important = important;
637 			}
638 		}
639 		else
640 		{
641 			m_properties[name] = property_value(val.c_str(), important);
642 		}
643 	}
644 }
645 
remove_property(const tstring & name,bool important)646 void litehtml::style::remove_property( const tstring& name, bool important )
647 {
648 	props_map::iterator prop = m_properties.find(name);
649 	if(prop != m_properties.end())
650 	{
651 		if( !prop->second.m_important || (important && prop->second.m_important) )
652 		{
653 			m_properties.erase(prop);
654 		}
655 	}
656 }
657