add support for Ayatana indicator to Notification plugin
[claws.git] / src / plugins / litehtml_viewer / litehtml / formatting_context.cpp
blob4e41c7b5fa46e2374ec4ae576f85d539dbe0201a
1 #include "html.h"
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)
7 floated_box fb;
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();
14 fb.el = el;
15 fb.context = context;
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);
23 } else
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));
31 inserted = true;
32 break;
35 if(!inserted)
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));
46 } else
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));
54 inserted = true;
55 break;
58 if(!inserted)
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
69 int h = 0;
71 for(const auto& fb : m_floats_left)
73 bool process = false;
74 switch(el_float)
76 case float_none:
77 process = true;
78 break;
79 case float_left:
80 if (fb.clear_floats == clear_left || fb.clear_floats == clear_both)
82 process = true;
84 break;
85 case float_right:
86 if (fb.clear_floats == clear_right || fb.clear_floats == clear_both)
88 process = true;
90 break;
92 if(process)
94 if(el_float == float_none)
96 h = std::max(h, fb.pos.bottom());
97 } else
99 h = std::max(h, fb.pos.top());
105 for(const auto& fb : m_floats_right)
107 int process = false;
108 switch(el_float)
110 case float_none:
111 process = true;
112 break;
113 case float_left:
114 if (fb.clear_floats == clear_left || fb.clear_floats == clear_both)
116 process = true;
118 break;
119 case float_right:
120 if (fb.clear_floats == clear_right || fb.clear_floats == clear_both)
122 process = true;
124 break;
126 if(process)
128 if(el_float == float_none)
130 h = std::max(h, fb.pos.bottom());
131 } else
133 h = std::max(h, fb.pos.top());
138 return h - m_current_top;
141 int litehtml::formatting_context::get_left_floats_height() const
143 int h = 0;
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
156 int h = 0;
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 )
169 y += m_current_top;
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)
175 return 0;
177 return m_cache_line_left.val - m_current_left;
180 int w = 0;
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())
188 break;
192 m_cache_line_left.set_value(y, w);
193 w -= m_current_left;
194 if(w < 0) return 0;
195 return w;
198 int litehtml::formatting_context::get_line_right(int y, int def_right )
200 y += m_current_top;
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;
207 } else
209 int w = std::min(m_cache_line_right.val, def_right) - m_current_left;
210 if(w < 0) return 0;
211 return w;
215 int w = def_right;
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())
225 break;
229 m_cache_line_right.set_value(y, w);
230 w -= m_current_left;
231 if(w < 0) return 0;
232 return 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();
245 } else
247 iter++;
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();
258 } else
260 iter++;
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())
269 case clear_left:
271 int fh = get_left_floats_height();
272 if(fh && fh > line_top)
274 line_top = fh;
277 break;
278 case clear_right:
280 int fh = get_right_floats_height();
281 if(fh && fh > line_top)
283 line_top = fh;
286 break;
287 case clear_both:
289 int fh = get_floats_height(float_none);
290 if(fh && fh > line_top)
292 line_top = fh;
295 break;
296 default:
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)
302 line_top = fh;
305 break;
307 return 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;
315 int new_top = top;
316 int_vector points;
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());
354 if(!points.empty())
356 sort(points.begin(), points.end(), std::less<int>( ));
357 new_top = points.back();
359 for(auto pt : points)
361 int pos_left = 0;
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)
367 new_top = pt;
368 break;
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()))
382 reset_cache = true;
383 fb->pos.y += dy;
386 if(reset_cache)
388 m_cache_line_left.invalidate();
390 reset_cache = false;
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()))
395 reset_cache = true;
396 fb->pos.y += dy;
399 if(reset_cache)
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)
415 y += m_current_top;
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)
430 y += m_current_top;
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;