2 #include "render_block.h"
3 #include "render_inline_context.h"
4 #include "render_block_context.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
);
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
);
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();
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
;
53 std::shared_ptr
<litehtml::render_item
> litehtml::render_item_block::init()
57 sel
.parse(".inline_rating");
58 if(src_el()->select(sel
))
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());
79 else if (child
->css().get_display() == display_list_item
)
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());
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())
123 if(has_block_level
&& has_inlines
)
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())
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
);
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
;
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())
188 ret
->src_el()->add_render(ret
);
190 for(auto& el
: ret
->children())
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 //*****************************************
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
211 if(self_size
.width
.type
== containing_block_context::cbc_value_type_absolute
)
213 ret_width
= m_pos
.width
= self_size
.render_width
;
214 } else if(self_size
.width
.type
== containing_block_context::cbc_value_type_percentage
)
216 m_pos
.width
= self_size
.render_width
;
219 m_pos
.width
= self_size
.render_width
;
222 // Fix width with min-width attribute
223 if(self_size
.min_width
.type
!= containing_block_context::cbc_value_type_none
)
225 if(m_pos
.width
< self_size
.min_width
)
227 m_pos
.width
= self_size
.min_width
;
228 requires_rerender
= true;
232 // Fix width with max-width attribute
233 if(self_size
.max_width
.type
!= containing_block_context::cbc_value_type_none
)
235 if(m_pos
.width
> self_size
.max_width
)
237 m_pos
.width
= self_size
.max_width
;
238 requires_rerender
= true;
242 // re-render content with new width if required
243 if (requires_rerender
&& !second_pass
&& !is_root())
245 if(src_el()->is_block_formatting_context())
247 fmt_ctx
->clear_floats(-1);
250 fmt_ctx
->clear_floats(self_size
.context_idx
);
253 _render_content(x
, y
, true, self_size
.new_width(m_pos
.width
), fmt_ctx
);
257 if (self_size
.height
.type
!= containing_block_context::cbc_value_type_auto
)
259 if(self_size
.height
> 0)
261 m_pos
.height
= self_size
.height
;
263 if(src_el()->css().get_box_sizing() == box_sizing_border_box
)
265 m_pos
.height
-= box_sizing_height();
267 } else if (src_el()->is_block_formatting_context())
269 // add the floats' height to the block height
270 int floats_height
= fmt_ctx
->get_floats_height();
271 if (floats_height
> m_pos
.height
)
273 m_pos
.height
= floats_height
;
277 // Fix height with min-height attribute
278 if(self_size
.min_height
.type
!= containing_block_context::cbc_value_type_none
)
280 if(m_pos
.height
< self_size
.min_height
)
282 m_pos
.height
= self_size
.min_height
;
286 // Fix width with max-width attribute
287 if(self_size
.max_height
.type
!= containing_block_context::cbc_value_type_none
)
289 if(m_pos
.height
> self_size
.max_height
)
291 m_pos
.height
= self_size
.max_height
;
295 // calculate the final position
297 m_pos
.x
+= content_offset_left();
298 m_pos
.y
+= content_offset_top();
300 if (src_el()->css().get_display() == display_list_item
)
302 string list_image
= src_el()->css().get_list_style_image();
303 if (!list_image
.empty())
306 string list_image_baseurl
= src_el()->css().get_list_style_image_baseurl();
307 src_el()->get_document()->container()->get_image_size(list_image
.c_str(), list_image_baseurl
.c_str(), sz
);
308 if (m_pos
.height
< sz
.height
)
310 m_pos
.height
= sz
.height
;
316 return ret_width
+ content_offset_width();