Disable stack execution on plugins
[claws.git] / src / plugins / litehtml_viewer / litehtml / style.cpp
blob5642d36c4dd4ca669fd1e439aa2bc7ab3e5eb741
1 #include "html.h"
2 #include "style.h"
4 namespace litehtml
7 std::map<string_id, string> style::m_valid_values =
9 { _display_, style_display_strings },
10 { _visibility_, visibility_strings },
11 { _position_, element_position_strings },
12 { _float_, element_float_strings },
13 { _clear_, element_clear_strings },
14 { _overflow_, overflow_strings },
15 { _box_sizing_, box_sizing_strings },
17 { _text_align_, text_align_strings },
18 { _vertical_align_, vertical_align_strings },
19 { _text_transform_, text_transform_strings },
20 { _white_space_, white_space_strings },
22 { _font_style_, font_style_strings },
23 { _font_variant_, font_variant_strings },
24 { _font_weight_, font_weight_strings },
26 { _list_style_type_, list_style_type_strings },
27 { _list_style_position_, list_style_position_strings },
29 { _border_left_style_, border_style_strings },
30 { _border_right_style_, border_style_strings },
31 { _border_top_style_, border_style_strings },
32 { _border_bottom_style_, border_style_strings },
33 { _border_collapse_, border_collapse_strings },
35 // these 4 properties are comma-separated lists of keywords, see parse_keyword_comma_list
36 { _background_attachment_, background_attachment_strings },
37 { _background_repeat_, background_repeat_strings },
38 { _background_clip_, background_box_strings },
39 { _background_origin_, background_box_strings },
41 { _flex_direction_, flex_direction_strings },
42 { _flex_wrap_, flex_wrap_strings },
43 { _justify_content_, flex_justify_content_strings },
44 { _align_items_, flex_align_items_strings },
45 { _align_content_, flex_align_content_strings },
46 { _align_self_, flex_align_self_strings },
48 { _caption_side_, caption_side_strings },
51 void style::parse(const string& txt, const string& baseurl, document_container* container)
53 std::vector<string> properties;
54 split_string(txt, properties, ";", "", "\"'");
56 for(const auto & property : properties)
58 parse_property(property, baseurl, container);
62 void style::parse_property(const string& txt, const string& baseurl, document_container* container)
64 string::size_type pos = txt.find_first_of(':');
65 if(pos != string::npos)
67 string name = txt.substr(0, pos);
68 string val = txt.substr(pos + 1);
70 trim(name); lcase(name);
71 trim(val);
73 if(!name.empty() && !val.empty())
75 string_vector vals;
76 split_string(val, vals, "!");
77 if(vals.size() == 1)
79 add_property(_id(name), val, baseurl, false, container);
80 } else if(vals.size() > 1)
82 trim(vals[0]);
83 lcase(vals[1]);
84 add_property(_id(name), vals[0], baseurl, vals[1] == "important", container);
90 void style::add_property(string_id name, const string& val, const string& baseurl, bool important, document_container* container)
92 if (val.find("var(") != -1) return add_parsed_property(name, property_value(val, important, prop_type_var));
93 if (val == "inherit" && name != _font_) return add_parsed_property(name, property_value(important, prop_type_inherit));
95 int idx;
96 string url;
97 css_length len[4], length;
99 switch (name)
101 // keyword-only properties
102 case _display_:
103 case _visibility_:
104 case _position_:
105 case _float_:
106 case _clear_:
107 case _box_sizing_:
108 case _overflow_:
110 case _text_align_:
111 case _vertical_align_:
112 case _text_transform_:
113 case _white_space_:
115 case _font_style_:
116 case _font_variant_:
117 case _font_weight_:
119 case _list_style_type_:
120 case _list_style_position_:
122 case _border_top_style_:
123 case _border_bottom_style_:
124 case _border_left_style_:
125 case _border_right_style_:
126 case _border_collapse_:
128 case _flex_direction_:
129 case _flex_wrap_:
130 case _justify_content_:
131 case _align_items_:
132 case _align_content_:
133 case _align_self_:
135 case _caption_side_:
137 idx = value_index(val, m_valid_values[name]);
138 if (idx >= 0)
140 add_parsed_property(name, property_value(idx, important));
142 break;
144 // <length>
145 case _text_indent_:
146 case _padding_left_:
147 case _padding_right_:
148 case _padding_top_:
149 case _padding_bottom_:
150 length.fromString(val);
151 add_parsed_property(name, property_value(length, important));
152 break;
154 // <length> | auto
155 case _left_:
156 case _right_:
157 case _top_:
158 case _bottom_:
159 case _z_index_: // <integer> | auto
160 case _width_:
161 case _height_:
162 case _min_width_:
163 case _min_height_:
164 case _margin_left_:
165 case _margin_right_:
166 case _margin_top_:
167 case _margin_bottom_:
168 length.fromString(val, "auto", -1);
169 add_parsed_property(name, property_value(length, important));
170 break;
172 // <length> | none
173 case _max_width_:
174 case _max_height_:
175 length.fromString(val, "none", -1);
176 add_parsed_property(name, property_value(length, important));
177 break;
179 case _line_height_:
180 length.fromString(val, "normal", -1);
181 add_parsed_property(name, property_value(length, important));
182 break;
184 case _font_size_:
185 length.fromString(val, font_size_strings, -1);
186 add_parsed_property(name, property_value(length, important));
187 break;
189 // Parse background shorthand properties
190 case _background_:
191 parse_background(val, baseurl, important, container);
192 break;
194 case _background_image_:
195 parse_background_image(val, baseurl, important);
196 break;
198 case _background_attachment_:
199 case _background_repeat_:
200 case _background_clip_:
201 case _background_origin_:
202 parse_keyword_comma_list(name, val, important);
203 break;
205 case _background_position_:
206 parse_background_position(val, important);
207 break;
209 case _background_size_:
210 parse_background_size(val, important);
211 break;
213 // Parse border spacing properties
214 case _border_spacing_:
215 parse_two_lengths(val, len);
216 add_parsed_property(__litehtml_border_spacing_x_, property_value(len[0], important));
217 add_parsed_property(__litehtml_border_spacing_y_, property_value(len[1], important));
218 break;
220 // Parse borders shorthand properties
221 case _border_:
223 string_vector tokens;
224 split_string(val, tokens, " ", "", "(");
225 for (const auto& token : tokens)
227 int idx = value_index(token, border_style_strings);
228 if (idx >= 0)
230 property_value style(idx, important);
231 add_parsed_property(_border_left_style_, style);
232 add_parsed_property(_border_right_style_, style);
233 add_parsed_property(_border_top_style_, style);
234 add_parsed_property(_border_bottom_style_, style);
236 else if (t_isdigit(token[0]) || token[0] == '.' ||
237 value_in_list(token, border_width_strings))
239 property_value width(parse_border_width(token), important);
240 add_parsed_property(_border_left_width_, width);
241 add_parsed_property(_border_right_width_, width);
242 add_parsed_property(_border_top_width_, width);
243 add_parsed_property(_border_bottom_width_, width);
245 else if (web_color::is_color(token, container))
247 web_color _color = web_color::from_string(token, container);
248 property_value color(_color, important);
249 add_parsed_property(_border_left_color_, color);
250 add_parsed_property(_border_right_color_, color);
251 add_parsed_property(_border_top_color_, color);
252 add_parsed_property(_border_bottom_color_, color);
255 break;
258 case _border_left_:
259 case _border_right_:
260 case _border_top_:
261 case _border_bottom_:
263 string_vector tokens;
264 split_string(val, tokens, " ", "", "(");
265 for (const auto& token : tokens)
267 int idx = value_index(token, border_style_strings);
268 if (idx >= 0)
270 add_parsed_property(_id(_s(name) + "-style"), property_value(idx, important));
272 else if (t_isdigit(token[0]) || token[0] == '.' ||
273 value_in_list(token, border_width_strings))
275 property_value width(parse_border_width(token), important);
276 add_parsed_property(_id(_s(name) + "-width"), width);
278 else if (web_color::is_color(token, container))
280 web_color color = web_color::from_string(token, container);
281 add_parsed_property(_id(_s(name) + "-color"), property_value(color, important));
284 break;
287 // Parse border-width/style/color shorthand properties
288 case _border_width_:
289 case _border_style_:
290 case _border_color_:
292 string prop = name == _border_width_ ? "-width" : name == _border_style_ ? "-style" : "-color";
294 string_vector tokens;
295 split_string(val, tokens, " ");
296 if (tokens.size() == 4)
298 add_property(_id("border-top" + prop), tokens[0], baseurl, important, container);
299 add_property(_id("border-right" + prop), tokens[1], baseurl, important, container);
300 add_property(_id("border-bottom" + prop), tokens[2], baseurl, important, container);
301 add_property(_id("border-left" + prop), tokens[3], baseurl, important, container);
303 else if (tokens.size() == 3)
305 add_property(_id("border-top" + prop), tokens[0], baseurl, important, container);
306 add_property(_id("border-right" + prop), tokens[1], baseurl, important, container);
307 add_property(_id("border-left" + prop), tokens[1], baseurl, important, container);
308 add_property(_id("border-bottom" + prop), tokens[2], baseurl, important, container);
310 else if (tokens.size() == 2)
312 add_property(_id("border-top" + prop), tokens[0], baseurl, important, container);
313 add_property(_id("border-bottom" + prop), tokens[0], baseurl, important, container);
314 add_property(_id("border-right" + prop), tokens[1], baseurl, important, container);
315 add_property(_id("border-left" + prop), tokens[1], baseurl, important, container);
317 else if (tokens.size() == 1)
319 add_property(_id("border-top" + prop), tokens[0], baseurl, important, container);
320 add_property(_id("border-bottom" + prop), tokens[0], baseurl, important, container);
321 add_property(_id("border-right" + prop), tokens[0], baseurl, important, container);
322 add_property(_id("border-left" + prop), tokens[0], baseurl, important, container);
324 break;
327 case _border_top_width_:
328 case _border_bottom_width_:
329 case _border_left_width_:
330 case _border_right_width_:
331 length = parse_border_width(val);
332 add_parsed_property(name, property_value(length, important));
333 break;
335 case _color_:
336 case _background_color_:
337 case _border_top_color_:
338 case _border_bottom_color_:
339 case _border_left_color_:
340 case _border_right_color_:
341 if (web_color::is_color(val, container))
343 web_color color = web_color::from_string(val, container);
344 add_parsed_property(name, property_value(color, important));
346 break;
348 // Parse border radius shorthand properties
349 case _border_bottom_left_radius_:
350 case _border_bottom_right_radius_:
351 case _border_top_right_radius_:
352 case _border_top_left_radius_:
353 parse_two_lengths(val, len);
354 add_parsed_property(_id(_s(name) + "-x"), property_value(len[0], important));
355 add_parsed_property(_id(_s(name) + "-y"), property_value(len[1], important));
356 break;
358 // Parse border-radius shorthand properties
359 case _border_radius_:
361 string_vector tokens;
362 split_string(val, tokens, "/");
363 if (tokens.size() == 1)
365 add_property(_border_radius_x_, tokens[0], baseurl, important, container);
366 add_property(_border_radius_y_, tokens[0], baseurl, important, container);
368 else if (tokens.size() >= 2)
370 add_property(_border_radius_x_, tokens[0], baseurl, important, container);
371 add_property(_border_radius_y_, tokens[1], baseurl, important, container);
373 break;
375 case _border_radius_x_:
376 case _border_radius_y_:
378 string_id top_left, top_right, bottom_right, bottom_left;
379 if (name == _border_radius_x_)
381 top_left = _border_top_left_radius_x_;
382 top_right = _border_top_right_radius_x_;
383 bottom_right = _border_bottom_right_radius_x_;
384 bottom_left = _border_bottom_left_radius_x_;
386 else
388 top_left = _border_top_left_radius_y_;
389 top_right = _border_top_right_radius_y_;
390 bottom_right = _border_bottom_right_radius_y_;
391 bottom_left = _border_bottom_left_radius_y_;
394 switch (parse_four_lengths(val, len))
396 case 1:
397 add_parsed_property(top_left, property_value(len[0], important));
398 add_parsed_property(top_right, property_value(len[0], important));
399 add_parsed_property(bottom_right, property_value(len[0], important));
400 add_parsed_property(bottom_left, property_value(len[0], important));
401 break;
402 case 2:
403 add_parsed_property(top_left, property_value(len[0], important));
404 add_parsed_property(top_right, property_value(len[1], important));
405 add_parsed_property(bottom_right, property_value(len[0], important));
406 add_parsed_property(bottom_left, property_value(len[1], important));
407 break;
408 case 3:
409 add_parsed_property(top_left, property_value(len[0], important));
410 add_parsed_property(top_right, property_value(len[1], important));
411 add_parsed_property(bottom_right, property_value(len[2], important));
412 add_parsed_property(bottom_left, property_value(len[1], important));
413 break;
414 case 4:
415 add_parsed_property(top_left, property_value(len[0], important));
416 add_parsed_property(top_right, property_value(len[1], important));
417 add_parsed_property(bottom_right, property_value(len[2], important));
418 add_parsed_property(bottom_left, property_value(len[3], important));
419 break;
421 break;
424 // Parse list-style shorthand properties
425 case _list_style_:
427 add_parsed_property(_list_style_type_, property_value(list_style_type_disc, important));
428 add_parsed_property(_list_style_position_, property_value(list_style_position_outside, important));
429 add_parsed_property(_list_style_image_, property_value("", important));
430 add_parsed_property(_list_style_image_baseurl_, property_value("", important));
432 string_vector tokens;
433 split_string(val, tokens, " ", "", "(");
434 for (const auto& token : tokens)
436 int idx = value_index(token, list_style_type_strings);
437 if (idx >= 0)
439 add_parsed_property(_list_style_type_, property_value(idx, important));
441 else
443 idx = value_index(token, list_style_position_strings);
444 if (idx >= 0)
446 add_parsed_property(_list_style_position_, property_value(idx, important));
448 else if (!strncmp(token.c_str(), "url", 3))
450 css::parse_css_url(token, url);
451 add_parsed_property(_list_style_image_, property_value(url, important));
452 add_parsed_property(_list_style_image_baseurl_, property_value(baseurl, important));
456 break;
459 case _list_style_image_:
460 css::parse_css_url(val, url);
461 add_parsed_property(_list_style_image_, property_value(url, important));
462 add_parsed_property(_list_style_image_baseurl_, property_value(baseurl, important));
463 break;
465 // Parse margin and padding shorthand properties
466 case _margin_:
467 case _padding_:
469 switch (parse_four_lengths(val, len))
471 case 4:
472 add_parsed_property(_id(_s(name) + "-top"), property_value(len[0], important));
473 add_parsed_property(_id(_s(name) + "-right"), property_value(len[1], important));
474 add_parsed_property(_id(_s(name) + "-bottom"), property_value(len[2], important));
475 add_parsed_property(_id(_s(name) + "-left"), property_value(len[3], important));
476 break;
477 case 3:
478 add_parsed_property(_id(_s(name) + "-top"), property_value(len[0], important));
479 add_parsed_property(_id(_s(name) + "-right"), property_value(len[1], important));
480 add_parsed_property(_id(_s(name) + "-left"), property_value(len[1], important));
481 add_parsed_property(_id(_s(name) + "-bottom"), property_value(len[2], important));
482 break;
483 case 2:
484 add_parsed_property(_id(_s(name) + "-top"), property_value(len[0], important));
485 add_parsed_property(_id(_s(name) + "-bottom"), property_value(len[0], important));
486 add_parsed_property(_id(_s(name) + "-right"), property_value(len[1], important));
487 add_parsed_property(_id(_s(name) + "-left"), property_value(len[1], important));
488 break;
489 case 1:
490 add_parsed_property(_id(_s(name) + "-top"), property_value(len[0], important));
491 add_parsed_property(_id(_s(name) + "-bottom"), property_value(len[0], important));
492 add_parsed_property(_id(_s(name) + "-right"), property_value(len[0], important));
493 add_parsed_property(_id(_s(name) + "-left"), property_value(len[0], important));
494 break;
496 break;
499 // Parse font shorthand properties
500 case _font_:
501 parse_font(val, important);
502 break;
504 // Parse flex-flow shorthand properties
505 case _flex_flow_:
507 string_vector tokens;
508 split_string(val, tokens, " ");
509 for (const auto& tok : tokens)
511 int idx;
512 if ((idx = value_index(tok, flex_direction_strings)) >= 0)
514 add_parsed_property(_flex_direction_, property_value(idx, important));
516 else if ((idx = value_index(tok, flex_wrap_strings)) >= 0)
518 add_parsed_property(_flex_wrap_, property_value(idx, important));
521 break;
524 // Parse flex shorthand properties
525 case _flex_:
526 parse_flex(val, important);
527 break;
529 case _flex_grow_:
530 case _flex_shrink_:
531 add_parsed_property(name, property_value(t_strtof(val), important));
532 break;
534 case _flex_basis_:
535 length.fromString(val, flex_basis_strings, -1);
536 add_parsed_property(_flex_basis_, property_value(length, important));
537 break;
539 default:
540 add_parsed_property(name, property_value(val, important));
544 css_length style::parse_border_width(const string& str)
546 css_length len;
547 if (t_isdigit(str[0]) || str[0] == '.')
549 len.fromString(str);
551 else
553 int idx = value_index(str, border_width_strings);
554 if (idx >= 0)
556 len.set_value(border_width_values[idx], css_units_px);
559 return len;
562 void style::parse_two_lengths(const string& str, css_length len[2])
564 string_vector tokens;
565 split_string(str, tokens, " ");
566 if (tokens.size() == 1)
568 css_length length;
569 length.fromString(tokens[0]);
570 len[0] = len[1] = length;
572 else if (tokens.size() == 2)
574 len[0].fromString(tokens[0]);
575 len[1].fromString(tokens[1]);
579 int style::parse_four_lengths(const string& str, css_length len[4])
581 string_vector tokens;
582 split_string(str, tokens, " ");
583 if (tokens.size() == 0 || tokens.size() > 4)
585 return 0;
587 for (size_t i = 0; i < tokens.size(); i++)
589 len[i].fromString(tokens[i]);
591 return (int)tokens.size();
594 void style::parse_background(const string& val, const string& baseurl, bool important, document_container* container)
596 string_vector tokens;
597 split_string(val, tokens, ",", "", "(");
598 if (tokens.empty()) return;
600 web_color color;
601 string_vector images;
602 int_vector repeats, origins, clips, attachments;
603 length_vector x_positions, y_positions;
604 size_vector sizes;
606 for (const auto& token : tokens)
608 background bg;
609 if (!parse_one_background(token, container, bg))
610 return;
612 color = bg.m_color;
613 images.push_back(bg.m_image[0]);
614 repeats.push_back(bg.m_repeat[0]);
615 origins.push_back(bg.m_origin[0]);
616 clips.push_back(bg.m_clip[0]);
617 attachments.push_back(bg.m_attachment[0]);
618 x_positions.push_back(bg.m_position_x[0]);
619 y_positions.push_back(bg.m_position_y[0]);
620 sizes.push_back(bg.m_size[0]);
623 add_parsed_property(_background_color_, property_value(color, important));
624 add_parsed_property(_background_image_, property_value(images, important));
625 add_parsed_property(_background_image_baseurl_, property_value(baseurl, important));
626 add_parsed_property(_background_repeat_, property_value(repeats, important));
627 add_parsed_property(_background_origin_, property_value(origins, important));
628 add_parsed_property(_background_clip_, property_value(clips, important));
629 add_parsed_property(_background_attachment_, property_value(attachments, important));
630 add_parsed_property(_background_position_x_, property_value(x_positions, important));
631 add_parsed_property(_background_position_y_, property_value(y_positions, important));
632 add_parsed_property(_background_size_, property_value(sizes, important));
635 bool style::parse_one_background(const string& val, document_container* container, background& bg)
637 bg.m_color = web_color::transparent;
638 bg.m_image = {""};
639 bg.m_repeat = { background_repeat_repeat };
640 bg.m_origin = { background_box_padding };
641 bg.m_clip = { background_box_border };
642 bg.m_attachment = { background_attachment_scroll };
643 bg.m_position_x = { css_length(0, css_units_percentage) };
644 bg.m_position_y = { css_length(0, css_units_percentage) };
645 bg.m_size = { css_size(css_length::predef_value(background_size_auto), css_length::predef_value(background_size_auto)) };
647 if(val == "none")
649 return true;
652 string_vector tokens;
653 split_string(val, tokens, " \t\n\r", "", "(");
655 bool color_found = false;
656 bool image_found = false;
657 bool origin_found = false;
658 bool clip_found = false;
659 bool repeat_found = false;
660 bool attachment_found = false;
662 string position;
663 for(const auto& token : tokens)
665 int idx;
666 if(token.substr(0, 3) == "url")
668 if (image_found) return false;
669 string url;
670 css::parse_css_url(token, url);
671 bg.m_image = { url };
672 image_found = true;
673 } else if( (idx = value_index(token, background_repeat_strings)) >= 0 )
675 if (repeat_found) return false;
676 bg.m_repeat = { idx };
677 repeat_found = true;
678 } else if( (idx = value_index(token, background_attachment_strings)) >= 0 )
680 if (attachment_found) return false;
681 bg.m_attachment = { idx };
682 attachment_found = true;
683 } else if( (idx = value_index(token, background_box_strings)) >= 0 )
685 if(!origin_found)
687 bg.m_origin = { idx };
688 origin_found = true;
689 } else
691 if (clip_found) return false;
692 bg.m_clip = { idx };
693 clip_found = true;
695 } else if( value_in_list(token, background_position_strings) ||
696 token.find('/') != -1 ||
697 t_isdigit(token[0]) ||
698 token[0] == '+' ||
699 token[0] == '-' ||
700 token[0] == '.' )
702 position += " " + token;
703 } else if (web_color::is_color(token, container))
705 if (color_found) return false;
706 bg.m_color = web_color::from_string(token, container);
707 color_found = true;
709 else
711 return false;
715 if (position != "")
717 string_vector tokens;
718 split_string(position, tokens, "/");
720 if (tokens.size() > 2) return false;
722 if (tokens.size() == 2 && !parse_one_background_size(tokens[1], bg.m_size[0]))
723 return false;
725 if (tokens.size() > 0 && !parse_one_background_position(tokens[0], bg.m_position_x[0], bg.m_position_y[0]))
726 return false;
729 return true;
732 void style::parse_background_image(const string& val, const string& baseurl, bool important)
734 string_vector tokens;
735 split_string(val, tokens, ",", "", "(");
736 if (tokens.empty()) return;
738 string_vector images;
740 for (const auto& token : tokens)
742 string url;
743 css::parse_css_url(token, url);
744 images.push_back(url);
747 add_parsed_property(_background_image_, property_value(images, important));
748 add_parsed_property(_background_image_baseurl_, property_value(baseurl, important));
751 void style::parse_keyword_comma_list(string_id name, const string& val, bool important)
753 string_vector tokens;
754 split_string(val, tokens, ",");
755 if (tokens.empty()) return;
757 int_vector vec;
759 for (auto& token : tokens)
761 trim(token);
762 int idx = value_index(token, m_valid_values[name]);
763 if (idx == -1) return;
764 vec.push_back(idx);
767 add_parsed_property(name, property_value(vec, important));
770 void style::parse_background_position(const string& val, bool important)
772 string_vector tokens;
773 split_string(val, tokens, ",");
774 if (tokens.empty()) return;
776 length_vector x_positions, y_positions;
778 for (const auto& token : tokens)
780 css_length x, y;
781 if(!parse_one_background_position(token, x, y)) return;
782 x_positions.push_back(x);
783 y_positions.push_back(y);
786 add_parsed_property(_background_position_x_, property_value(x_positions, important));
787 add_parsed_property(_background_position_y_, property_value(y_positions, important));
790 bool style::parse_one_background_position(const string& val, css_length& x, css_length& y)
792 string_vector pos;
793 split_string(val, pos, " \t");
795 if (pos.empty() || pos.size() > 2)
797 return false;
800 if (pos.size() == 1)
802 if (value_in_list(pos[0], "left;right;center"))
804 x.fromString(pos[0], "left;right;center");
805 y.set_value(50, css_units_percentage);
807 else if (value_in_list(pos[0], "top;bottom;center"))
809 y.fromString(pos[0], "top;bottom;center");
810 x.set_value(50, css_units_percentage);
812 else
814 x.fromString(pos[0], "left;right;center");
815 y.set_value(50, css_units_percentage);
818 else if (pos.size() == 2)
820 if (value_in_list(pos[0], "left;right"))
822 x.fromString(pos[0], "left;right;center");
823 y.fromString(pos[1], "top;bottom;center");
825 else if (value_in_list(pos[0], "top;bottom"))
827 x.fromString(pos[1], "left;right;center");
828 y.fromString(pos[0], "top;bottom;center");
830 else if (value_in_list(pos[1], "left;right"))
832 x.fromString(pos[1], "left;right;center");
833 y.fromString(pos[0], "top;bottom;center");
835 else if (value_in_list(pos[1], "top;bottom"))
837 x.fromString(pos[0], "left;right;center");
838 y.fromString(pos[1], "top;bottom;center");
840 else
842 x.fromString(pos[0], "left;right;center");
843 y.fromString(pos[1], "top;bottom;center");
847 if (x.is_predefined())
849 switch (x.predef())
851 case 0:
852 x.set_value(0, css_units_percentage);
853 break;
854 case 1:
855 x.set_value(100, css_units_percentage);
856 break;
857 case 2:
858 x.set_value(50, css_units_percentage);
859 break;
862 if (y.is_predefined())
864 switch (y.predef())
866 case 0:
867 y.set_value(0, css_units_percentage);
868 break;
869 case 1:
870 y.set_value(100, css_units_percentage);
871 break;
872 case 2:
873 y.set_value(50, css_units_percentage);
874 break;
877 return true;
880 void style::parse_background_size(const string& val, bool important)
882 string_vector tokens;
883 split_string(val, tokens, ",");
884 if (tokens.empty()) return;
886 size_vector sizes;
888 for (const auto& token : tokens)
890 css_size size;
891 if (!parse_one_background_size(token, size)) return;
892 sizes.push_back(size);
895 add_parsed_property(_background_size_, property_value(sizes, important));
898 bool style::parse_one_background_size(const string& val, css_size& size)
900 string_vector res;
901 split_string(val, res, " \t");
902 if (res.empty())
904 return false;
907 size.width.fromString(res[0], background_size_strings);
908 if (res.size() > 1)
910 size.height.fromString(res[1], background_size_strings);
912 else
914 size.height.predef(background_size_auto);
916 return true;
919 void style::parse_font(const string& val, bool important)
921 if (val == "inherit")
923 add_parsed_property(_font_style_, property_value(important, prop_type_inherit));
924 add_parsed_property(_font_variant_, property_value(important, prop_type_inherit));
925 add_parsed_property(_font_weight_, property_value(important, prop_type_inherit));
926 add_parsed_property(_font_size_, property_value(important, prop_type_inherit));
927 add_parsed_property(_line_height_, property_value(important, prop_type_inherit));
928 return;
929 } else
931 add_parsed_property(_font_style_, property_value(font_style_normal, important));
932 add_parsed_property(_font_variant_, property_value(font_variant_normal, important));
933 add_parsed_property(_font_weight_, property_value(font_weight_normal, important));
934 add_parsed_property(_font_size_, property_value(font_size_medium, important));
935 add_parsed_property(_line_height_, property_value(line_height_normal, important));
938 string_vector tokens;
939 split_string(val, tokens, " ", "", "\"");
941 int idx;
942 bool is_family = false;
943 string font_family;
944 for(const auto& token : tokens)
946 if(is_family)
948 font_family += token;
949 continue;
952 if((idx = value_index(token, font_style_strings)) >= 0)
954 if(idx == 0)
956 add_parsed_property(_font_style_, property_value(font_style_normal, important));
957 add_parsed_property(_font_variant_, property_value(font_variant_normal, important));
958 add_parsed_property(_font_weight_, property_value(font_weight_normal, important));
959 } else
961 add_parsed_property(_font_style_, property_value(idx, important));
963 } else if((idx = value_index(token, font_weight_strings)) >= 0)
965 add_parsed_property(_font_weight_, property_value(idx, important));
966 } else if((idx = value_index(token, font_variant_strings)) >= 0)
968 add_parsed_property(_font_variant_, property_value(idx, important));
970 else if(t_isdigit(token[0]) || token[0] == '.' ||
971 value_in_list(token, font_size_strings) || token.find('/') != -1)
973 string_vector szlh;
974 split_string(token, szlh, "/");
976 auto size = css_length::from_string(szlh[0], font_size_strings, -1);
977 add_parsed_property(_font_size_, property_value(size, important));
979 if(szlh.size() == 2)
981 auto height = css_length::from_string(szlh[1], "normal", -1);
982 add_parsed_property(_line_height_, property_value(height, important));
984 } else
986 is_family = true;
987 font_family += token;
990 add_parsed_property(_font_family_, property_value(font_family, important));
993 void style::parse_flex(const string& val, bool important)
995 auto is_number = [](const string& val)
997 for (auto ch : val)
999 if ((ch < '0' || ch > '9') && ch != '.')
1001 return false;
1004 return true;
1007 css_length _auto = css_length::predef_value(flex_basis_auto);
1009 if (val == "initial")
1011 // 0 1 auto
1012 add_parsed_property(_flex_grow_, property_value(0.f, important));
1013 add_parsed_property(_flex_shrink_, property_value(1.f, important));
1014 add_parsed_property(_flex_basis_, property_value(_auto, important));
1016 else if (val == "auto")
1018 // 1 1 auto
1019 add_parsed_property(_flex_grow_, property_value(1.f, important));
1020 add_parsed_property(_flex_shrink_, property_value(1.f, important));
1021 add_parsed_property(_flex_basis_, property_value(_auto, important));
1023 else if (val == "none")
1025 // 0 0 auto
1026 add_parsed_property(_flex_grow_, property_value(0.f, important));
1027 add_parsed_property(_flex_shrink_, property_value(0.f, important));
1028 add_parsed_property(_flex_basis_, property_value(_auto, important));
1030 else
1032 string_vector tokens;
1033 split_string(val, tokens, " ");
1034 if (tokens.size() == 3)
1036 float grow = t_strtof(tokens[0]);
1037 float shrink = t_strtof(tokens[1]);
1038 auto basis = css_length::from_string(tokens[2], flex_basis_strings, -1);
1040 add_parsed_property(_flex_grow_, property_value(grow, important));
1041 add_parsed_property(_flex_shrink_, property_value(shrink, important));
1042 add_parsed_property(_flex_basis_, property_value(basis, important));
1044 else if (tokens.size() == 2)
1046 float grow = t_strtof(tokens[0]);
1047 add_parsed_property(_flex_grow_, property_value(grow, important));
1049 if (is_number(tokens[1]))
1051 float shrink = t_strtof(tokens[1]);
1052 add_parsed_property(_flex_shrink_, property_value(shrink, important));
1054 else
1056 auto basis = css_length::from_string(tokens[1], flex_basis_strings, -1);
1057 add_parsed_property(_flex_basis_, property_value(basis, important));
1060 else if (tokens.size() == 1)
1062 if (is_number(tokens[0]))
1064 float grow = t_strtof(tokens[0]);
1065 add_parsed_property(_flex_grow_, property_value(grow, important));
1067 if (grow >= 1)
1069 add_parsed_property(_flex_shrink_, property_value(1.f, important));
1070 add_parsed_property(_flex_basis_, property_value(css_length(0), important));
1073 else
1075 auto basis = css_length::from_string(tokens[0], flex_basis_strings, -1);
1076 add_parsed_property(_flex_basis_, property_value(basis, important));
1082 void style::add_parsed_property( string_id name, const property_value& propval )
1084 auto prop = m_properties.find(name);
1085 if (prop != m_properties.end())
1087 if (!prop->second.m_important || (propval.m_important && prop->second.m_important))
1089 prop->second = propval;
1092 else
1094 m_properties[name] = propval;
1098 void style::remove_property( string_id name, bool important )
1100 auto prop = m_properties.find(name);
1101 if(prop != m_properties.end())
1103 if( !prop->second.m_important || (important && prop->second.m_important) )
1105 m_properties.erase(prop);
1110 void style::combine(const style& src)
1112 for (const auto& property : src.m_properties)
1114 add_parsed_property(property.first, property.second);
1118 const property_value& style::get_property(string_id name) const
1120 auto it = m_properties.find(name);
1121 if (it != m_properties.end())
1123 return it->second;
1125 static property_value dummy;
1126 return dummy;
1129 void style::subst_vars_(string& str, const element* el)
1131 while (1)
1133 auto start = str.find("var(");
1134 if (start == -1) break;
1135 if (start > 0 && isalnum(str[start - 1])) break;
1136 auto end = str.find(")", start + 4);
1137 if (end == -1) break;
1138 auto name = str.substr(start + 4, end - start - 4);
1139 trim(name);
1140 string val = el->get_custom_property(_id(name), "");
1141 str.replace(start, end - start + 1, val);
1145 void style::subst_vars(const element* el)
1147 for (auto& prop : m_properties)
1149 if (prop.second.m_type == prop_type_var)
1151 subst_vars_(prop.second.m_string, el);
1152 // re-adding the same property
1153 // if it is a custom property it will be readded as a string (currently it is prop_type_var)
1154 // if it is a standard css property it will be parsed and properly added as typed property
1155 add_property(prop.first, prop.second.m_string, "", prop.second.m_important, el->get_document()->container());
1160 } // namespace litehtml