vCalendar: Honor VTIMEZONE component if present
[claws.git] / src / plugins / litehtml_viewer / litehtml / render_block.cpp
blobc170c341fcab4349705d266475f8ea0e636f0089
1 #include "html.h"
2 #include "render_block.h"
3 #include "render_inline_context.h"
4 #include "render_block_context.h"
5 #include "document.h"
7 int litehtml::render_item_block::place_float(const std::shared_ptr<render_item> &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx)
9 int line_top = fmt_ctx->get_cleared_top(el, top);
10 int line_left = 0;
11 int line_right = self_size.render_width;
12 fmt_ctx->get_line_left_right(line_top, self_size.render_width, line_left, line_right);
14 int ret_width = 0;
16 int min_rendered_width = el->render(line_left, line_top, self_size.new_width(line_right), fmt_ctx);
17 if(min_rendered_width < el->width() && el->src_el()->css().get_width().is_predefined())
19 el->render(line_left, line_top, self_size.new_width(min_rendered_width), fmt_ctx);
22 if (el->src_el()->css().get_float() == float_left)
24 if(el->right() > line_right)
26 line_top = fmt_ctx->find_next_line_top(el->top(), el->width(), self_size.render_width);
27 el->pos().x = fmt_ctx->get_line_left(line_top) + el->content_offset_left();
28 el->pos().y = line_top + el->content_offset_top();
30 fmt_ctx->add_float(el, min_rendered_width, self_size.context_idx);
31 fix_line_width(float_left, self_size, fmt_ctx);
33 ret_width = fmt_ctx->find_min_left(line_top, self_size.context_idx);
34 } else if (el->src_el()->css().get_float() == float_right)
36 if(line_left + el->width() > line_right)
38 int new_top = fmt_ctx->find_next_line_top(el->top(), el->width(), self_size.render_width);
39 el->pos().x = fmt_ctx->get_line_right(new_top, self_size.render_width) - el->width() + el->content_offset_left();
40 el->pos().y = new_top + el->content_offset_top();
41 } else
43 el->pos().x = line_right - el->width() + el->content_offset_left();
45 fmt_ctx->add_float(el, min_rendered_width, self_size.context_idx);
46 fix_line_width(float_right, self_size, fmt_ctx);
47 line_right = fmt_ctx->find_min_right(line_top, self_size.render_width, self_size.context_idx);
48 ret_width = self_size.render_width - line_right;
50 return ret_width;
53 std::shared_ptr<litehtml::render_item> litehtml::render_item_block::init()
56 css_selector sel;
57 sel.parse(".inline_rating");
58 if(src_el()->select(sel))
60 int i = 0;
61 i++;
64 std::shared_ptr<render_item> ret;
66 // Initialize indexes for list items
67 if(src_el()->css().get_display() == display_list_item && src_el()->css().get_list_style_type() >= list_style_type_armenian)
69 if (auto p = src_el()->parent())
71 int val = atoi(p->get_attr("start", "1"));
72 for(const auto &child : p->children())
74 if (child == src_el())
76 src_el()->set_attr("list_index", std::to_string(val).c_str());
77 break;
79 else if (child->css().get_display() == display_list_item)
80 val++;
84 // Split inline blocks with box blocks inside
85 auto iter = m_children.begin();
86 while (iter != m_children.end())
88 const auto& el = *iter;
89 if(el->src_el()->css().get_display() == display_inline && !el->children().empty())
91 auto split_el = el->split_inlines();
92 if(std::get<0>(split_el))
94 iter = m_children.erase(iter);
95 iter = m_children.insert(iter, std::get<2>(split_el));
96 iter = m_children.insert(iter, std::get<1>(split_el));
97 iter = m_children.insert(iter, std::get<0>(split_el));
99 std::get<0>(split_el)->parent(shared_from_this());
100 std::get<1>(split_el)->parent(shared_from_this());
101 std::get<2>(split_el)->parent(shared_from_this());
102 continue;
105 ++iter;
108 bool has_block_level = false;
109 bool has_inlines = false;
110 bool has_floats = false;
111 for (const auto& el : m_children)
113 if(!el->src_el()->is_float())
115 if (el->src_el()->is_block_box())
117 has_block_level = true;
118 } else if (el->src_el()->is_inline())
120 has_inlines = true;
123 if(has_block_level && has_inlines)
124 break;
126 if(has_block_level)
128 ret = std::make_shared<render_item_block_context>(src_el());
129 ret->parent(parent());
131 auto doc = src_el()->get_document();
132 decltype(m_children) new_children;
133 decltype(m_children) inlines;
134 bool not_ws_added = false;
135 for (const auto& el : m_children)
137 if(el->src_el()->is_inline())
139 inlines.push_back(el);
140 if(!el->src_el()->is_white_space())
141 not_ws_added = true;
142 } else
144 if(not_ws_added)
146 auto anon_el = std::make_shared<html_tag>(src_el());
147 auto anon_ri = std::make_shared<render_item_block>(anon_el);
148 for(const auto& inl : inlines)
150 anon_ri->add_child(inl);
153 not_ws_added = false;
154 new_children.push_back(anon_ri);
155 anon_ri->parent(ret);
157 new_children.push_back(el);
158 el->parent(ret);
159 inlines.clear();
162 if(!inlines.empty() && not_ws_added)
164 auto anon_el = std::make_shared<html_tag>(src_el());
165 auto anon_ri = std::make_shared<render_item_block>(anon_el);
166 for(const auto& inl : inlines)
168 anon_ri->add_child(inl);
171 new_children.push_back(anon_ri);
172 anon_ri->parent(ret);
174 ret->children() = new_children;
177 if(!ret)
179 ret = std::make_shared<render_item_inline_context>(src_el());
180 ret->parent(parent());
181 ret->children() = children();
182 for (const auto &el: ret->children())
184 el->parent(ret);
188 ret->src_el()->add_render(ret);
190 for(auto& el : ret->children())
192 el = el->init();
195 return ret;
198 int litehtml::render_item_block::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass)
200 containing_block_context self_size = calculate_containing_block_context(containing_block_size);
202 //*****************************************
203 // Render content
204 //*****************************************
205 int ret_width = _render_content(x, y, second_pass, self_size, fmt_ctx);
206 //*****************************************
208 bool requires_rerender = false; // when true, the second pass for content rendering is required
210 // Set block width
211 if(!(containing_block_size.size_mode & containing_block_context::size_mode_content))
213 if(self_size.width.type == containing_block_context::cbc_value_type_absolute)
215 ret_width = m_pos.width = self_size.render_width;
216 } else
218 m_pos.width = self_size.render_width;
220 } else
222 m_pos.width = ret_width;
223 if(self_size.width.type == containing_block_context::cbc_value_type_absolute && ret_width > self_size.width)
225 ret_width = self_size.width;
229 // Fix width with max-width attribute
230 if(self_size.max_width.type != containing_block_context::cbc_value_type_none)
232 if(m_pos.width > self_size.max_width)
234 m_pos.width = self_size.max_width;
235 requires_rerender = true;
239 // Fix width with min-width attribute
240 if(self_size.min_width.type != containing_block_context::cbc_value_type_none)
242 if(m_pos.width < self_size.min_width)
244 m_pos.width = self_size.min_width;
245 requires_rerender = true;
247 } else if(m_pos.width < 0)
249 m_pos.width = 0;
252 // re-render content with new width if required
253 if (requires_rerender && !second_pass && !is_root())
255 if(src_el()->is_block_formatting_context())
257 fmt_ctx->clear_floats(-1);
258 } else
260 fmt_ctx->clear_floats(self_size.context_idx);
263 _render_content(x, y, true, self_size.new_width(m_pos.width), fmt_ctx);
266 // Set block height
267 if (self_size.height.type != containing_block_context::cbc_value_type_auto &&
268 !(containing_block_size.size_mode & containing_block_context::size_mode_content))
270 // TODO: Something wrong here
271 // Percentage height from undefined containing block height is usually <= 0
272 if(self_size.height.type == containing_block_context::cbc_value_type_percentage)
274 if (self_size.height > 0)
276 m_pos.height = self_size.height;
278 } else
280 m_pos.height = self_size.height;
282 if (src_el()->css().get_box_sizing() == box_sizing_border_box)
284 m_pos.height -= box_sizing_height();
286 } else if (src_el()->is_block_formatting_context())
288 // add the floats' height to the block height
289 int floats_height = fmt_ctx->get_floats_height();
290 if (floats_height > m_pos.height)
292 m_pos.height = floats_height;
295 if(containing_block_size.size_mode & containing_block_context::size_mode_content)
297 if(self_size.height.type == containing_block_context::cbc_value_type_absolute)
299 if(m_pos.height > self_size.height)
301 m_pos.height = self_size.height;
306 // Fix height with min-height attribute
307 if(self_size.min_height.type != containing_block_context::cbc_value_type_none)
309 if(m_pos.height < self_size.min_height)
311 m_pos.height = self_size.min_height;
313 } else if(m_pos.height < 0)
315 m_pos.height = 0;
318 // Fix width with max-width attribute
319 if(self_size.max_height.type != containing_block_context::cbc_value_type_none)
321 if(m_pos.height > self_size.max_height)
323 m_pos.height = self_size.max_height;
327 // calculate the final position
328 m_pos.move_to(x, y);
329 m_pos.x += content_offset_left();
330 m_pos.y += content_offset_top();
332 if (src_el()->css().get_display() == display_list_item)
334 string list_image = src_el()->css().get_list_style_image();
335 if (!list_image.empty())
337 size sz;
338 string list_image_baseurl = src_el()->css().get_list_style_image_baseurl();
339 src_el()->get_document()->container()->get_image_size(list_image.c_str(), list_image_baseurl.c_str(), sz);
340 if (m_pos.height < sz.height)
342 m_pos.height = sz.height;
348 return ret_width + content_offset_width();