2 #include "render_item.h"
5 #include <utf8_strings.h>
7 litehtml::render_item::render_item(std::shared_ptr
<element
> _src_el
) :
8 m_element(std::move(_src_el
)),
11 document::ptr doc
= src_el()->get_document();
12 auto fnt_size
= src_el()->css().get_font_size();
14 m_margins
.left
= doc
->to_pixels(src_el()->css().get_margins().left
, fnt_size
);
15 m_margins
.right
= doc
->to_pixels(src_el()->css().get_margins().right
, fnt_size
);
16 m_margins
.top
= doc
->to_pixels(src_el()->css().get_margins().top
, fnt_size
);
17 m_margins
.bottom
= doc
->to_pixels(src_el()->css().get_margins().bottom
, fnt_size
);
19 m_padding
.left
= doc
->to_pixels(src_el()->css().get_padding().left
, fnt_size
);
20 m_padding
.right
= doc
->to_pixels(src_el()->css().get_padding().right
, fnt_size
);
21 m_padding
.top
= doc
->to_pixels(src_el()->css().get_padding().top
, fnt_size
);
22 m_padding
.bottom
= doc
->to_pixels(src_el()->css().get_padding().bottom
, fnt_size
);
24 m_borders
.left
= doc
->to_pixels(src_el()->css().get_borders().left
.width
, fnt_size
);
25 m_borders
.right
= doc
->to_pixels(src_el()->css().get_borders().right
.width
, fnt_size
);
26 m_borders
.top
= doc
->to_pixels(src_el()->css().get_borders().top
.width
, fnt_size
);
27 m_borders
.bottom
= doc
->to_pixels(src_el()->css().get_borders().bottom
.width
, fnt_size
);
30 int litehtml::render_item::render(int x
, int y
, const containing_block_context
& containing_block_size
, formatting_context
* fmt_ctx
, bool second_pass
)
34 calc_outlines(containing_block_size
.width
);
39 int content_left
= content_offset_left();
40 int content_top
= content_offset_top();
42 m_pos
.x
+= content_left
;
43 m_pos
.y
+= content_top
;
46 if(src_el()->is_block_formatting_context() || ! fmt_ctx
)
48 formatting_context fmt
;
49 fmt
.push_position(content_left
, content_top
);
50 ret
= _render(x
, y
, containing_block_size
, &fmt
, second_pass
);
51 fmt
.apply_relative_shift(containing_block_size
);
54 fmt_ctx
->push_position(x
+ content_left
, y
+ content_top
);
55 ret
= _render(x
, y
, containing_block_size
, fmt_ctx
, second_pass
);
56 fmt_ctx
->pop_position(x
+ content_left
, y
+ content_top
);
61 void litehtml::render_item::calc_outlines( int parent_width
)
63 m_padding
.left
= m_element
->css().get_padding().left
.calc_percent(parent_width
);
64 m_padding
.right
= m_element
->css().get_padding().right
.calc_percent(parent_width
);
66 m_borders
.left
= m_element
->css().get_borders().left
.width
.calc_percent(parent_width
);
67 m_borders
.right
= m_element
->css().get_borders().right
.width
.calc_percent(parent_width
);
69 m_margins
.left
= m_element
->css().get_margins().left
.calc_percent(parent_width
);
70 m_margins
.right
= m_element
->css().get_margins().right
.calc_percent(parent_width
);
72 m_margins
.top
= m_element
->css().get_margins().top
.calc_percent(parent_width
);
73 m_margins
.bottom
= m_element
->css().get_margins().bottom
.calc_percent(parent_width
);
75 m_padding
.top
= m_element
->css().get_padding().top
.calc_percent(parent_width
);
76 m_padding
.bottom
= m_element
->css().get_padding().bottom
.calc_percent(parent_width
);
79 int litehtml::render_item::calc_auto_margins(int parent_width
)
81 if ((src_el()->css().get_display() == display_block
|| src_el()->css().get_display() == display_table
) &&
82 src_el()->css().get_position() != element_position_absolute
&&
83 src_el()->css().get_float() == float_none
)
85 if (src_el()->css().get_margins().left
.is_predefined() && src_el()->css().get_margins().right
.is_predefined())
87 int el_width
= m_pos
.width
+ m_borders
.left
+ m_borders
.right
+ m_padding
.left
+ m_padding
.right
;
88 if (el_width
<= parent_width
)
90 m_margins
.left
= (parent_width
- el_width
) / 2;
91 m_margins
.right
= (parent_width
- el_width
) - m_margins
.left
;
98 return m_margins
.left
;
100 else if (src_el()->css().get_margins().left
.is_predefined() && !src_el()->css().get_margins().right
.is_predefined())
102 int el_width
= m_pos
.width
+ m_borders
.left
+ m_borders
.right
+ m_padding
.left
+ m_padding
.right
+ m_margins
.right
;
103 m_margins
.left
= parent_width
- el_width
;
104 if (m_margins
.left
< 0) m_margins
.left
= 0;
105 return m_margins
.left
;
107 else if (!src_el()->css().get_margins().left
.is_predefined() && src_el()->css().get_margins().right
.is_predefined())
109 int el_width
= m_pos
.width
+ m_borders
.left
+ m_borders
.right
+ m_padding
.left
+ m_padding
.right
+ m_margins
.left
;
110 m_margins
.right
= parent_width
- el_width
;
111 if (m_margins
.right
< 0) m_margins
.right
= 0;
117 void litehtml::render_item::apply_relative_shift(const containing_block_context
&containing_block_size
)
119 if (src_el()->css().get_position() == element_position_relative
)
121 css_offsets offsets
= src_el()->css().get_offsets();
122 if (!offsets
.left
.is_predefined())
124 m_pos
.x
+= offsets
.left
.calc_percent(containing_block_size
.width
);
126 else if (!offsets
.right
.is_predefined())
128 m_pos
.x
-= offsets
.right
.calc_percent(containing_block_size
.width
);
130 if (!offsets
.top
.is_predefined())
132 m_pos
.y
+= offsets
.top
.calc_percent(containing_block_size
.height
);
134 else if (!offsets
.bottom
.is_predefined())
136 m_pos
.y
-= offsets
.bottom
.calc_percent(containing_block_size
.height
);
141 bool litehtml::render_item::get_predefined_height(int& p_height
, int containing_block_height
) const
143 css_length h
= src_el()->css().get_height();
144 if(h
.is_predefined())
146 p_height
= m_pos
.height
;
149 if(h
.units() == css_units_percentage
)
151 p_height
= h
.calc_percent(containing_block_height
);
152 return containing_block_height
> 0;
154 p_height
= src_el()->get_document()->to_pixels(h
, src_el()->css().get_font_size());
158 int litehtml::render_item::calc_width(int defVal
, int containing_block_width
) const
160 css_length w
= src_el()->css().get_width();
161 if(w
.is_predefined() || src_el()->css().get_display() == display_table_cell
)
165 if(w
.units() == css_units_percentage
)
167 return w
.calc_percent(containing_block_width
);
169 return src_el()->get_document()->to_pixels(w
, src_el()->css().get_font_size());
173 std::shared_ptr
<litehtml::render_item
>,
174 std::shared_ptr
<litehtml::render_item
>,
175 std::shared_ptr
<litehtml::render_item
>
176 > litehtml::render_item::split_inlines()
179 std::shared_ptr
<litehtml::render_item
>,
180 std::shared_ptr
<litehtml::render_item
>,
181 std::shared_ptr
<litehtml::render_item
>
183 for(const auto& child
: m_children
)
185 if(child
->src_el()->is_block_box() && child
->src_el()->css().get_float() == float_none
)
187 std::get
<0>(ret
) = clone();
188 std::get
<1>(ret
) = child
;
189 std::get
<2>(ret
) = clone();
191 std::get
<1>(ret
)->parent(std::get
<0>(ret
));
192 std::get
<2>(ret
)->parent(std::get
<0>(ret
));
195 for(const auto& ch
: m_children
)
204 std::get
<0>(ret
)->add_child(ch
);
207 std::get
<2>(ret
)->add_child(ch
);
212 if(!child
->children().empty())
214 auto child_split
= child
->split_inlines();
215 if(std::get
<0>(child_split
))
217 std::get
<0>(ret
) = clone();
218 std::get
<1>(ret
) = std::get
<1>(child_split
);
219 std::get
<2>(ret
) = clone();
221 std::get
<2>(ret
)->parent(std::get
<0>(ret
));
224 for(const auto& ch
: m_children
)
233 std::get
<0>(ret
)->add_child(ch
);
236 std::get
<2>(ret
)->add_child(ch
);
239 std::get
<0>(ret
)->add_child(std::get
<0>(child_split
));
240 std::get
<2>(ret
)->add_child(std::get
<2>(child_split
));
248 bool litehtml::render_item::fetch_positioned()
252 m_positioned
.clear();
254 litehtml::element_position el_pos
;
256 for(auto& el
: m_children
)
258 el_pos
= el
->src_el()->css().get_position();
259 if (el_pos
!= element_position_static
)
263 if (!ret
&& (el_pos
== element_position_absolute
|| el_pos
== element_position_fixed
))
267 if(el
->fetch_positioned())
275 void litehtml::render_item::render_positioned(render_type rt
)
277 position wnd_position
;
278 src_el()->get_document()->container()->get_client_rect(wnd_position
);
280 element_position el_position
;
282 for (auto& el
: m_positioned
)
284 el_position
= el
->src_el()->css().get_position();
287 if(el
->src_el()->css().get_display() != display_none
)
289 if(el_position
== element_position_absolute
)
291 if(rt
!= render_fixed_only
)
295 } else if(el_position
== element_position_fixed
)
297 if(rt
!= render_no_fixed
)
306 containing_block_context containing_block_size
;
309 if(el_position
== element_position_fixed
)
311 containing_block_size
.height
= wnd_position
.height
;
312 containing_block_size
.width
= wnd_position
.width
;
313 client_x
= wnd_position
.left();
314 client_y
= wnd_position
.top();
317 containing_block_size
.height
= m_pos
.height
;
318 containing_block_size
.width
= m_pos
.width
;
321 css_length css_left
= el
->src_el()->css().get_offsets().left
;
322 css_length css_right
= el
->src_el()->css().get_offsets().right
;
323 css_length css_top
= el
->src_el()->css().get_offsets().top
;
324 css_length css_bottom
= el
->src_el()->css().get_offsets().bottom
;
326 bool need_render
= false;
328 css_length el_w
= el
->src_el()->css().get_width();
329 css_length el_h
= el
->src_el()->css().get_height();
333 if(el_w
.units() == css_units_percentage
&& containing_block_size
.width
)
335 new_width
= el_w
.calc_percent(containing_block_size
.width
);
336 if(el
->m_pos
.width
!= new_width
)
339 el
->m_pos
.width
= new_width
;
343 if(el_h
.units() == css_units_percentage
&& containing_block_size
.height
)
345 new_height
= el_h
.calc_percent(containing_block_size
.height
);
346 if(el
->m_pos
.height
!= new_height
)
349 el
->m_pos
.height
= new_height
;
356 if(el_position
== element_position_fixed
)
358 if(!css_left
.is_predefined() || !css_right
.is_predefined())
360 if(!css_left
.is_predefined() && css_right
.is_predefined())
362 el
->m_pos
.x
= css_left
.calc_percent(containing_block_size
.width
) + el
->content_offset_left();
363 } else if(css_left
.is_predefined() && !css_right
.is_predefined())
365 el
->m_pos
.x
= containing_block_size
.width
- css_right
.calc_percent(containing_block_size
.width
) - el
->m_pos
.width
-
366 el
->content_offset_right();
369 el
->m_pos
.x
= css_left
.calc_percent(containing_block_size
.width
) + el
->content_offset_left();
370 el
->m_pos
.width
= containing_block_size
.width
-
371 css_left
.calc_percent(containing_block_size
.width
) -
372 css_right
.calc_percent(containing_block_size
.width
) -
373 (el
->content_offset_left() + el
->content_offset_right());
378 if(!css_top
.is_predefined() || !css_bottom
.is_predefined())
380 if(!css_top
.is_predefined() && css_bottom
.is_predefined())
382 el
->m_pos
.y
= css_top
.calc_percent(containing_block_size
.height
) + el
->content_offset_top();
383 } else if(css_top
.is_predefined() && !css_bottom
.is_predefined())
385 el
->m_pos
.y
= containing_block_size
.height
- css_bottom
.calc_percent(containing_block_size
.height
) - el
->m_pos
.height
-
386 el
->content_offset_bottom();
389 el
->m_pos
.y
= css_top
.calc_percent(containing_block_size
.height
) + el
->content_offset_top();
390 el
->m_pos
.height
= containing_block_size
.height
-
391 css_top
.calc_percent(containing_block_size
.height
) -
392 css_bottom
.calc_percent(containing_block_size
.height
) -
393 (el
->content_offset_top() + el
->content_offset_bottom());
399 if(!css_left
.is_predefined() || !css_right
.is_predefined())
401 if(!css_left
.is_predefined() && css_right
.is_predefined())
403 el
->m_pos
.x
= css_left
.calc_percent(containing_block_size
.height
) + el
->content_offset_left() - m_padding
.left
;
404 } else if(css_left
.is_predefined() && !css_right
.is_predefined())
406 el
->m_pos
.x
= m_pos
.width
+ m_padding
.right
- css_right
.calc_percent(containing_block_size
.height
) - el
->m_pos
.width
-
407 el
->content_offset_right();
410 el
->m_pos
.x
= css_left
.calc_percent(containing_block_size
.height
) + el
->content_offset_left() - m_padding
.left
;
411 el
->m_pos
.width
= m_pos
.width
+ m_padding
.left
+ m_padding
.right
-
412 css_left
.calc_percent(containing_block_size
.height
) -
413 css_right
.calc_percent(containing_block_size
.height
) -
414 (el
->content_offset_left() + el
->content_offset_right());
417 el
->m_pos
.x
+= (el
->m_pos
.width
- new_width
) / 2;
418 el
->m_pos
.width
= new_width
;
425 if(!css_top
.is_predefined() || !css_bottom
.is_predefined())
427 if(!css_top
.is_predefined() && css_bottom
.is_predefined())
429 el
->m_pos
.y
= css_top
.calc_percent(containing_block_size
.height
) + el
->content_offset_top() - m_padding
.top
;
430 } else if(css_top
.is_predefined() && !css_bottom
.is_predefined())
432 el
->m_pos
.y
= m_pos
.height
+ m_padding
.bottom
- css_bottom
.calc_percent(containing_block_size
.height
) - el
->m_pos
.height
-
433 el
->content_offset_bottom();
436 el
->m_pos
.y
= css_top
.calc_percent(containing_block_size
.height
) + el
->content_offset_top() - m_padding
.top
;
437 el
->m_pos
.height
= m_pos
.height
+ m_padding
.top
+ m_padding
.bottom
-
438 css_top
.calc_percent(containing_block_size
.height
) -
439 css_bottom
.calc_percent(containing_block_size
.height
) -
440 (el
->content_offset_top() + el
->content_offset_bottom());
441 if (new_height
!= -1)
443 el
->m_pos
.y
+= (el
->m_pos
.height
- new_height
) / 2;
444 el
->m_pos
.height
= new_height
;
456 auto cur_el
= el
->parent();
457 auto this_el
= shared_from_this();
458 while(cur_el
&& cur_el
!= this_el
)
460 offset_x
+= cur_el
->m_pos
.x
;
461 offset_y
+= cur_el
->m_pos
.y
;
462 cur_el
= cur_el
->parent();
464 if(cvt_x
) el
->m_pos
.x
-= offset_x
;
465 if(cvt_y
) el
->m_pos
.y
-= offset_y
;
470 position pos
= el
->m_pos
;
471 el
->render(el
->left(), el
->top(), containing_block_size
.new_width(el
->width()), nullptr, true);
475 if(el_position
== element_position_fixed
)
478 el
->get_redraw_box(fixed_pos
);
479 src_el()->get_document()->add_fixed_box(fixed_pos
);
483 el
->render_positioned();
486 if(!m_positioned
.empty())
488 std::stable_sort(m_positioned
.begin(), m_positioned
.end(), [](const std::shared_ptr
<render_item
>& Left
, const std::shared_ptr
<render_item
>& Right
)
490 return (Left
->src_el()->css().get_z_index() < Right
->src_el()->css().get_z_index());
495 void litehtml::render_item::add_positioned(const std::shared_ptr
<litehtml::render_item
> &el
)
497 if (src_el()->css().get_position() != element_position_static
|| is_root())
499 m_positioned
.push_back(el
);
502 auto el_parent
= parent();
505 el_parent
->add_positioned(el
);
510 void litehtml::render_item::get_redraw_box(litehtml::position
& pos
, int x
/*= 0*/, int y
/*= 0*/)
514 int p_left
= std::min(pos
.left(), x
+ m_pos
.left() - m_padding
.left
- m_borders
.left
);
515 int p_right
= std::max(pos
.right(), x
+ m_pos
.right() + m_padding
.left
+ m_borders
.left
);
516 int p_top
= std::min(pos
.top(), y
+ m_pos
.top() - m_padding
.top
- m_borders
.top
);
517 int p_bottom
= std::max(pos
.bottom(), y
+ m_pos
.bottom() + m_padding
.bottom
+ m_borders
.bottom
);
521 pos
.width
= p_right
- p_left
;
522 pos
.height
= p_bottom
- p_top
;
524 if(src_el()->css().get_overflow() == overflow_visible
)
526 for(auto& el
: m_children
)
528 if(el
->src_el()->css().get_position() != element_position_fixed
)
530 el
->get_redraw_box(pos
, x
+ m_pos
.x
, y
+ m_pos
.y
);
537 void litehtml::render_item::calc_document_size( litehtml::size
& sz
, litehtml::size
& content_size
, int x
/*= 0*/, int y
/*= 0*/ )
539 if(is_visible() && src_el()->css().get_position() != element_position_fixed
)
541 sz
.width
= std::max(sz
.width
, x
+ right());
542 sz
.height
= std::max(sz
.height
, y
+ bottom());
544 if(!src_el()->is_root() && !src_el()->is_body())
546 content_size
.width
= std::max(content_size
.width
, x
+ right());
547 content_size
.height
= std::max(content_size
.height
, y
+ bottom());
550 // All children of tables and blocks with style other than "overflow: visible" are inside element.
551 // We can skip calculating size of children
552 if(src_el()->css().get_overflow() == overflow_visible
&& src_el()->css().get_display() != display_table
)
554 for(auto& el
: m_children
)
556 el
->calc_document_size(sz
, content_size
, x
+ m_pos
.x
, y
+ m_pos
.y
);
560 if(src_el()->is_root() || src_el()->is_body())
562 content_size
.width
+= content_offset_right();
563 content_size
.height
+= content_offset_bottom();
568 void litehtml::render_item::draw_stacking_context( uint_ptr hdc
, int x
, int y
, const position
* clip
, bool with_positioned
)
570 if(!is_visible()) return;
572 std::map
<int, bool> z_indexes
;
575 for(const auto& idx
: m_positioned
)
577 z_indexes
[idx
->src_el()->css().get_z_index()];
580 for(const auto& idx
: z_indexes
)
584 draw_children(hdc
, x
, y
, clip
, draw_positioned
, idx
.first
);
588 draw_children(hdc
, x
, y
, clip
, draw_block
, 0);
589 draw_children(hdc
, x
, y
, clip
, draw_floats
, 0);
590 draw_children(hdc
, x
, y
, clip
, draw_inlines
, 0);
593 for(auto& z_index
: z_indexes
)
595 if(z_index
.first
== 0)
597 draw_children(hdc
, x
, y
, clip
, draw_positioned
, z_index
.first
);
601 for(auto& z_index
: z_indexes
)
603 if(z_index
.first
> 0)
605 draw_children(hdc
, x
, y
, clip
, draw_positioned
, z_index
.first
);
611 void litehtml::render_item::draw_children(uint_ptr hdc
, int x
, int y
, const position
* clip
, draw_flag flag
, int zindex
)
613 position pos
= m_pos
;
617 document::ptr doc
= src_el()->get_document();
619 if (src_el()->css().get_overflow() > overflow_visible
)
621 // TODO: Process overflow for inline elements
622 if(src_el()->css().get_display() != display_inline
)
624 position border_box
= pos
;
625 border_box
+= m_padding
;
626 border_box
+= m_borders
;
628 border_radiuses bdr_radius
= src_el()->css().get_borders().radius
.calc_percents(border_box
.width
,
631 bdr_radius
-= m_borders
;
632 bdr_radius
-= m_padding
;
634 doc
->container()->set_clip(pos
, bdr_radius
);
638 for (const auto& el
: m_children
)
640 if (el
->is_visible())
645 case draw_positioned
:
646 if (el
->src_el()->is_positioned() && el
->src_el()->css().get_z_index() == zindex
)
648 if (el
->src_el()->css().get_position() == element_position_fixed
)
650 position browser_wnd
;
651 doc
->container()->get_client_rect(browser_wnd
);
653 el
->src_el()->draw(hdc
, browser_wnd
.x
, browser_wnd
.y
, clip
, el
);
654 el
->draw_stacking_context(hdc
, browser_wnd
.x
, browser_wnd
.y
, clip
, true);
658 el
->src_el()->draw(hdc
, pos
.x
, pos
.y
, clip
, el
);
659 el
->draw_stacking_context(hdc
, pos
.x
, pos
.y
, clip
, true);
665 if (!el
->src_el()->is_inline() && el
->src_el()->css().get_float() == float_none
&& !el
->src_el()->is_positioned())
667 el
->src_el()->draw(hdc
, pos
.x
, pos
.y
, clip
, el
);
671 if (el
->src_el()->css().get_float() != float_none
&& !el
->src_el()->is_positioned())
673 el
->src_el()->draw(hdc
, pos
.x
, pos
.y
, clip
, el
);
674 el
->draw_stacking_context(hdc
, pos
.x
, pos
.y
, clip
, false);
679 if (el
->src_el()->is_inline() && el
->src_el()->css().get_float() == float_none
&& !el
->src_el()->is_positioned())
681 el
->src_el()->draw(hdc
, pos
.x
, pos
.y
, clip
, el
);
682 if (el
->src_el()->css().get_display() == display_inline_block
)
684 el
->draw_stacking_context(hdc
, pos
.x
, pos
.y
, clip
, false);
695 if (flag
== draw_positioned
)
697 if (!el
->src_el()->is_positioned())
699 el
->draw_children(hdc
, pos
.x
, pos
.y
, clip
, flag
, zindex
);
704 if (el
->src_el()->css().get_float() == float_none
&&
705 el
->src_el()->css().get_display() != display_inline_block
&&
706 !el
->src_el()->is_positioned())
708 el
->draw_children(hdc
, pos
.x
, pos
.y
, clip
, flag
, zindex
);
715 if (src_el()->css().get_overflow() > overflow_visible
)
717 doc
->container()->del_clip();
721 std::shared_ptr
<litehtml::element
> litehtml::render_item::get_child_by_point(int x
, int y
, int client_x
, int client_y
, draw_flag flag
, int zindex
)
723 element::ptr ret
= nullptr;
725 if(src_el()->css().get_overflow() > overflow_visible
)
727 if(!m_pos
.is_point_inside(x
, y
))
733 position el_pos
= m_pos
;
734 el_pos
.x
= x
- el_pos
.x
;
735 el_pos
.y
= y
- el_pos
.y
;
737 for(auto i
= m_children
.rbegin(); i
!= m_children
.rend() && !ret
; std::advance(i
, 1))
741 if(el
->is_visible() && el
->src_el()->css().get_display() != display_inline_text
)
745 case draw_positioned
:
746 if(el
->src_el()->is_positioned() && el
->src_el()->css().get_z_index() == zindex
)
748 if(el
->src_el()->css().get_position() == element_position_fixed
)
750 ret
= el
->get_element_by_point(client_x
, client_y
, client_x
, client_y
);
751 if(!ret
&& (*i
)->is_point_inside(client_x
, client_y
))
753 ret
= (*i
)->src_el();
757 ret
= el
->get_element_by_point(el_pos
.x
, el_pos
.y
, client_x
, client_y
);
758 if(!ret
&& (*i
)->is_point_inside(el_pos
.x
, el_pos
.y
))
760 ret
= (*i
)->src_el();
767 if(!el
->src_el()->is_inline() && el
->src_el()->css().get_float() == float_none
&& !el
->src_el()->is_positioned())
769 if(el
->is_point_inside(el_pos
.x
, el_pos
.y
))
776 if(el
->src_el()->css().get_float() != float_none
&& !el
->src_el()->is_positioned())
778 ret
= el
->get_element_by_point(el_pos
.x
, el_pos
.y
, client_x
, client_y
);
780 if(!ret
&& (*i
)->is_point_inside(el_pos
.x
, el_pos
.y
))
782 ret
= (*i
)->src_el();
788 if(el
->src_el()->is_inline() && el
->src_el()->css().get_float() == float_none
&& !el
->src_el()->is_positioned())
790 if(el
->src_el()->css().get_display() == display_inline_block
||
791 el
->src_el()->css().get_display() == display_inline_table
||
792 el
->src_el()->css().get_display() == display_inline_flex
)
794 ret
= el
->get_element_by_point(el_pos
.x
, el_pos
.y
, client_x
, client_y
);
797 if(!ret
&& (*i
)->is_point_inside(el_pos
.x
, el_pos
.y
))
799 ret
= (*i
)->src_el();
807 if(el
&& !el
->src_el()->is_positioned())
809 if(flag
== draw_positioned
)
811 element::ptr child
= el
->get_child_by_point(el_pos
.x
, el_pos
.y
, client_x
, client_y
, flag
, zindex
);
818 if( el
->src_el()->css().get_float() == float_none
&&
819 el
->src_el()->css().get_display() != display_inline_block
)
821 element::ptr child
= el
->get_child_by_point(el_pos
.x
, el_pos
.y
, client_x
, client_y
, flag
, zindex
);
835 std::shared_ptr
<litehtml::element
> litehtml::render_item::get_element_by_point(int x
, int y
, int client_x
, int client_y
)
837 if(!is_visible()) return nullptr;
841 std::map
<int, bool> z_indexes
;
843 for(const auto& i
: m_positioned
)
845 z_indexes
[i
->src_el()->css().get_z_index()];
848 for(const auto& zindex
: z_indexes
)
852 ret
= get_child_by_point(x
, y
, client_x
, client_y
, draw_positioned
, zindex
.first
);
858 for(const auto& z_index
: z_indexes
)
860 if(z_index
.first
== 0)
862 ret
= get_child_by_point(x
, y
, client_x
, client_y
, draw_positioned
, z_index
.first
);
868 ret
= get_child_by_point(x
, y
, client_x
, client_y
, draw_inlines
, 0);
871 ret
= get_child_by_point(x
, y
, client_x
, client_y
, draw_floats
, 0);
874 ret
= get_child_by_point(x
, y
, client_x
, client_y
, draw_block
, 0);
878 for(const auto& z_index
: z_indexes
)
880 if(z_index
.first
< 0)
882 ret
= get_child_by_point(x
, y
, client_x
, client_y
, draw_positioned
, z_index
.first
);
888 if(src_el()->css().get_position() == element_position_fixed
)
890 if(is_point_inside(client_x
, client_y
))
896 if(is_point_inside(x
, y
))
905 bool litehtml::render_item::is_point_inside( int x
, int y
)
907 if(src_el()->css().get_display() != display_inline
&& src_el()->css().get_display() != display_table_row
)
909 position pos
= m_pos
;
912 if(pos
.is_point_inside(x
, y
))
921 position::vector boxes
;
922 get_inline_boxes(boxes
);
923 for(auto & box
: boxes
)
925 if(box
.is_point_inside(x
, y
))
934 void litehtml::render_item::get_rendering_boxes( position::vector
& redraw_boxes
)
936 if(src_el()->css().get_display() == display_inline
|| src_el()->css().get_display() == display_table_row
)
938 get_inline_boxes(redraw_boxes
);
941 position pos
= m_pos
;
944 redraw_boxes
.push_back(pos
);
947 if(src_el()->css().get_position() != element_position_fixed
)
949 auto cur_el
= parent();
952 for(auto& box
: redraw_boxes
)
954 box
.x
+= cur_el
->m_pos
.x
;
955 box
.y
+= cur_el
->m_pos
.y
;
957 cur_el
= cur_el
->parent();
962 void litehtml::render_item::dump(litehtml::dumper
& cout
)
964 cout
.begin_node(src_el()->dump_get_name() + "{" + string(typeid(*this).name()) + "}");
966 auto attrs
= src_el()->dump_get_attrs();
969 cout
.begin_attrs_group("attributes");
970 for (const auto &attr
: attrs
)
972 cout
.add_attr(std::get
<0>(attr
), std::get
<1>(attr
));
974 cout
.end_attrs_group();
977 if(!m_children
.empty())
979 cout
.begin_attrs_group("children");
980 for (const auto &el
: m_children
)
984 cout
.end_attrs_group();
990 litehtml::position
litehtml::render_item::get_placement() const
992 litehtml::position pos
= m_pos
;
993 auto cur_el
= parent();
996 pos
.x
+= cur_el
->m_pos
.x
;
997 pos
.y
+= cur_el
->m_pos
.y
;
998 cur_el
= cur_el
->parent();
1003 std::shared_ptr
<litehtml::render_item
> litehtml::render_item::init()
1005 src_el()->add_render(shared_from_this());
1007 for(auto& el
: children())
1012 return shared_from_this();
1015 void litehtml::render_item::calc_cb_length(const css_length
& len
, int percent_base
, containing_block_context::typed_int
& out_value
) const
1017 if (!len
.is_predefined())
1019 if(len
.units() == litehtml::css_units_percentage
)
1021 out_value
.value
= len
.calc_percent(percent_base
);
1022 out_value
.type
= litehtml::containing_block_context::cbc_value_type_percentage
;
1025 out_value
.value
= src_el()->get_document()->to_pixels(len
, src_el()->css().get_font_size());
1026 out_value
.type
= containing_block_context::cbc_value_type_absolute
;
1031 litehtml::containing_block_context
litehtml::render_item::calculate_containing_block_context(const containing_block_context
& cb_context
)
1033 containing_block_context ret
;
1034 ret
.context_idx
= cb_context
.context_idx
+ 1;
1035 ret
.width
.value
= ret
.max_width
.value
= cb_context
.width
.value
- content_offset_width();
1036 if(src_el()->css().get_position() != element_position_absolute
&& src_el()->css().get_position() != element_position_fixed
)
1038 ret
.height
.value
= cb_context
.height
.value
- content_offset_height();
1041 // Calculate width if css property is not auto
1042 // We have to use aut value for display_table_cell also.
1043 if (src_el()->css().get_display() != display_table_cell
)
1045 calc_cb_length(src_el()->css().get_width(), cb_context
.width
, ret
.width
);
1046 calc_cb_length(src_el()->css().get_height(), cb_context
.height
, ret
.height
);
1047 if (ret
.width
.type
!= containing_block_context::cbc_value_type_auto
&& (src_el()->css().get_display() == display_table
|| src_el()->is_root()))
1049 ret
.width
.value
-= content_offset_width();
1051 if (ret
.height
.type
!= containing_block_context::cbc_value_type_auto
&& (src_el()->css().get_display() == display_table
|| src_el()->is_root()))
1053 ret
.height
.value
-= content_offset_height();
1056 ret
.render_width
= ret
.width
;
1058 calc_cb_length(src_el()->css().get_min_width(), cb_context
.width
, ret
.min_width
);
1059 calc_cb_length(src_el()->css().get_max_width(), cb_context
.width
, ret
.max_width
);
1061 calc_cb_length(src_el()->css().get_min_height(), cb_context
.height
, ret
.min_height
);
1062 calc_cb_length(src_el()->css().get_max_height(), cb_context
.height
, ret
.max_height
);
1064 if (src_el()->css().get_box_sizing() == box_sizing_border_box
)
1066 if(ret
.width
.type
!= containing_block_context::cbc_value_type_auto
)
1068 ret
.render_width
= ret
.width
- box_sizing_width();
1070 if(ret
.min_width
.type
!= containing_block_context::cbc_value_type_none
)
1072 ret
.min_width
.value
-= box_sizing_width();
1074 if(ret
.max_width
.type
!= containing_block_context::cbc_value_type_none
)
1076 ret
.max_width
.value
-= box_sizing_width();
1078 if(ret
.min_height
.type
!= containing_block_context::cbc_value_type_none
)
1080 ret
.min_height
.value
-= box_sizing_height();
1082 if(ret
.max_height
.type
!= containing_block_context::cbc_value_type_none
)
1084 ret
.max_height
.value
-= box_sizing_height();