2 #include "render_item.h"
3 #include "formatting_context.h"
5 void litehtml::formatting_context::add_float(const std::shared_ptr
<render_item
> &el
, int min_width
, int context
)
8 fb
.pos
.x
= el
->left() + m_current_left
;
9 fb
.pos
.y
= el
->top() + m_current_top
;
10 fb
.pos
.width
= el
->width();
11 fb
.pos
.height
= el
->height();
12 fb
.float_side
= el
->src_el()->css().get_float();
13 fb
.clear_floats
= el
->src_el()->css().get_clear();
16 fb
.min_width
= min_width
;
18 if(fb
.float_side
== float_left
)
20 if(m_floats_left
.empty())
22 m_floats_left
.push_back(fb
);
25 bool inserted
= false;
26 for(auto i
= m_floats_left
.begin(); i
!= m_floats_left
.end(); i
++)
28 if(fb
.pos
.right() > i
->pos
.right())
30 m_floats_left
.insert(i
, std::move(fb
));
37 m_floats_left
.push_back(std::move(fb
));
40 m_cache_line_left
.invalidate();
41 } else if(fb
.float_side
== float_right
)
43 if(m_floats_right
.empty())
45 m_floats_right
.push_back(std::move(fb
));
48 bool inserted
= false;
49 for(auto i
= m_floats_right
.begin(); i
!= m_floats_right
.end(); i
++)
51 if(fb
.pos
.left() < i
->pos
.left())
53 m_floats_right
.insert(i
, std::move(fb
));
60 m_floats_right
.push_back(fb
);
63 m_cache_line_right
.invalidate();
67 int litehtml::formatting_context::get_floats_height(element_float el_float
) const
71 for(const auto& fb
: m_floats_left
)
80 if (fb
.clear_floats
== clear_left
|| fb
.clear_floats
== clear_both
)
86 if (fb
.clear_floats
== clear_right
|| fb
.clear_floats
== clear_both
)
94 if(el_float
== float_none
)
96 h
= std::max(h
, fb
.pos
.bottom());
99 h
= std::max(h
, fb
.pos
.top());
105 for(const auto& fb
: m_floats_right
)
114 if (fb
.clear_floats
== clear_left
|| fb
.clear_floats
== clear_both
)
120 if (fb
.clear_floats
== clear_right
|| fb
.clear_floats
== clear_both
)
128 if(el_float
== float_none
)
130 h
= std::max(h
, fb
.pos
.bottom());
133 h
= std::max(h
, fb
.pos
.top());
138 return h
- m_current_top
;
141 int litehtml::formatting_context::get_left_floats_height() const
144 if(!m_floats_left
.empty())
146 for (const auto& fb
: m_floats_left
)
148 h
= std::max(h
, fb
.pos
.bottom());
151 return h
- m_current_top
;
154 int litehtml::formatting_context::get_right_floats_height() const
157 if(!m_floats_right
.empty())
159 for(const auto& fb
: m_floats_right
)
161 h
= std::max(h
, fb
.pos
.bottom());
164 return h
- m_current_top
;
167 int litehtml::formatting_context::get_line_left(int y
)
171 if(m_cache_line_left
.is_valid
&& m_cache_line_left
.hash
== y
)
173 if(m_cache_line_left
.val
- m_current_left
< 0)
177 return m_cache_line_left
.val
- m_current_left
;
181 for(const auto& fb
: m_floats_left
)
183 if (y
>= fb
.pos
.top() && y
< fb
.pos
.bottom())
185 w
= std::max(w
, fb
.pos
.right());
186 if (w
< fb
.pos
.right())
192 m_cache_line_left
.set_value(y
, w
);
198 int litehtml::formatting_context::get_line_right(int y
, int def_right
)
201 def_right
+= m_current_left
;
202 if(m_cache_line_right
.is_valid
&& m_cache_line_right
.hash
== y
)
204 if(m_cache_line_right
.is_default
)
206 return def_right
- m_current_left
;
209 int w
= std::min(m_cache_line_right
.val
, def_right
) - m_current_left
;
216 m_cache_line_right
.is_default
= true;
217 for(const auto& fb
: m_floats_right
)
219 if(y
>= fb
.pos
.top() && y
< fb
.pos
.bottom())
221 w
= std::min(w
, fb
.pos
.left());
222 m_cache_line_right
.is_default
= false;
223 if(w
> fb
.pos
.left())
229 m_cache_line_right
.set_value(y
, w
);
236 void litehtml::formatting_context::clear_floats(int context
)
238 auto iter
= m_floats_left
.begin();
239 while(iter
!= m_floats_left
.end())
241 if(iter
->context
>= context
)
243 iter
= m_floats_left
.erase(iter
);
244 m_cache_line_left
.invalidate();
251 iter
= m_floats_right
.begin();
252 while(iter
!= m_floats_right
.end())
254 if(iter
->context
>= context
)
256 iter
= m_floats_right
.erase(iter
);
257 m_cache_line_right
.invalidate();
265 int litehtml::formatting_context::get_cleared_top(const std::shared_ptr
<render_item
> &el
, int line_top
) const
267 switch(el
->src_el()->css().get_clear())
271 int fh
= get_left_floats_height();
272 if(fh
&& fh
> line_top
)
280 int fh
= get_right_floats_height();
281 if(fh
&& fh
> line_top
)
289 int fh
= get_floats_height(float_none
);
290 if(fh
&& fh
> line_top
)
297 if(el
->src_el()->css().get_float() != float_none
)
299 int fh
= get_floats_height(el
->src_el()->css().get_float());
300 if(fh
&& fh
> line_top
)
310 int litehtml::formatting_context::find_next_line_top(int top
, int width
, int def_right
)
312 top
+= m_current_top
;
313 def_right
+= m_current_left
;
318 for(const auto& fb
: m_floats_left
)
320 if(fb
.pos
.top() >= top
)
322 if(find(points
.begin(), points
.end(), fb
.pos
.top()) == points
.end())
324 points
.push_back(fb
.pos
.top());
327 if (fb
.pos
.bottom() >= top
)
329 if (find(points
.begin(), points
.end(), fb
.pos
.bottom()) == points
.end())
331 points
.push_back(fb
.pos
.bottom());
336 for (const auto& fb
: m_floats_right
)
338 if (fb
.pos
.top() >= top
)
340 if (find(points
.begin(), points
.end(), fb
.pos
.top()) == points
.end())
342 points
.push_back(fb
.pos
.top());
345 if (fb
.pos
.bottom() >= top
)
347 if (find(points
.begin(), points
.end(), fb
.pos
.bottom()) == points
.end())
349 points
.push_back(fb
.pos
.bottom());
356 sort(points
.begin(), points
.end(), std::less
<int>( ));
357 new_top
= points
.back();
359 for(auto pt
: points
)
362 int pos_right
= def_right
;
363 get_line_left_right(pt
- m_current_top
, def_right
- m_current_left
, pos_left
, pos_right
);
365 if(pos_right
- pos_left
>= width
)
372 return new_top
- m_current_top
;
375 void litehtml::formatting_context::update_floats(int dy
, const std::shared_ptr
<render_item
> &parent
)
377 bool reset_cache
= false;
378 for(auto fb
= m_floats_left
.rbegin(); fb
!= m_floats_left
.rend(); fb
++)
380 if(fb
->el
->src_el()->is_ancestor(parent
->src_el()))
388 m_cache_line_left
.invalidate();
391 for(auto fb
= m_floats_right
.rbegin(); fb
!= m_floats_right
.rend(); fb
++)
393 if(fb
->el
->src_el()->is_ancestor(parent
->src_el()))
401 m_cache_line_right
.invalidate();
405 void litehtml::formatting_context::apply_relative_shift(const containing_block_context
&containing_block_size
)
407 for (const auto& fb
: m_floats_left
)
409 fb
.el
->apply_relative_shift(containing_block_size
);
413 int litehtml::formatting_context::find_min_left(int y
, int context_idx
)
416 int min_left
= m_current_left
;
417 for(const auto& fb
: m_floats_left
)
419 if (y
>= fb
.pos
.top() && y
< fb
.pos
.bottom() && fb
.context
== context_idx
)
421 min_left
+= fb
.min_width
;
424 if(min_left
< m_current_left
) return 0;
425 return min_left
- m_current_left
;
428 int litehtml::formatting_context::find_min_right(int y
, int right
, int context_idx
)
431 int min_right
= right
+ m_current_left
;
432 for(const auto& fb
: m_floats_right
)
434 if (y
>= fb
.pos
.top() && y
< fb
.pos
.bottom() && fb
.context
== context_idx
)
436 min_right
-= fb
.min_width
;
439 if(min_right
< m_current_left
) return 0;
440 return min_right
- m_current_left
;