Skip to content

Commit 9bc386d

Browse files
committed
Fixed: (min/max) width/height calculating with percent units.
1 parent 866f47a commit 9bc386d

19 files changed

+345
-361
lines changed

include/litehtml/line_box.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ namespace litehtml
3939
};
4040
protected:
4141
std::shared_ptr<render_item> m_element;
42+
int m_rendered_min_width;
4243
public:
43-
explicit line_box_item(const std::shared_ptr<render_item>& element) : m_element(element) {}
44+
explicit line_box_item(const std::shared_ptr<render_item>& element) : m_element(element), m_rendered_min_width(0) {}
4445
line_box_item() = default;
4546
line_box_item(const line_box_item& el) = default;
4647
line_box_item(line_box_item&&) = default;
@@ -55,6 +56,8 @@ namespace litehtml
5556
virtual int right() const;
5657
virtual int left() const;
5758
virtual element_type get_type() const { return type_text_part; }
59+
virtual int get_rendered_min_width() const { return m_rendered_min_width; }
60+
virtual void set_rendered_min_width(int min_width) { m_rendered_min_width = min_width; }
5861
};
5962

6063
class lbi_start : public line_box_item
@@ -72,6 +75,7 @@ namespace litehtml
7275
int right() const override;
7376
int left() const override;
7477
element_type get_type() const override { return type_inline_start; }
78+
int get_rendered_min_width() const override { return width(); }
7579
};
7680

7781
class lbi_end : public lbi_start
@@ -151,7 +155,7 @@ namespace litehtml
151155
int top_margin() const;
152156
int bottom_margin() const;
153157
void y_shift(int shift);
154-
std::list< std::unique_ptr<line_box_item> > finish(bool last_box = false);
158+
std::list< std::unique_ptr<line_box_item> > finish(bool last_box, const containing_block_context &containing_block_size);
155159
std::list< std::unique_ptr<line_box_item> > new_width(int left, int right);
156160
std::shared_ptr<render_item> get_last_text_part() const;
157161
std::shared_ptr<render_item> get_first_text_part() const;

include/litehtml/master_css.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ script {
3737
body {
3838
display:block;
3939
margin:8px;
40-
height:100%;
41-
width:100%;
4240
}
4341
4442
p {

include/litehtml/render_item.h

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ namespace litehtml
2626
bool m_skip;
2727
std::vector<std::shared_ptr<render_item>> m_positioned;
2828

29-
virtual int _render(int x, int y, int max_width, bool second_pass) { return 0; }
29+
virtual int _render(int x, int y, int max_width, const containing_block_context &containing_block_size, bool second_pass) { return 0; }
30+
containing_block_context calculate_containing_block_context(const containing_block_context& cb_context);
31+
void calc_cb_length(const css_length& len,
32+
int percent_base,
33+
int& out_value,
34+
containing_block_context::cbc_value_type& out_type);
3035

3136
public:
3237
explicit render_item(std::shared_ptr<element> src_el);
@@ -237,9 +242,9 @@ namespace litehtml
237242
ri->parent(shared_from_this());
238243
}
239244

240-
int render(int x, int y, int max_width)
245+
int render(int x, int y, int max_width, const containing_block_context& containing_block_size)
241246
{
242-
return _render(x, y, max_width, false);
247+
return _render(x, y, max_width, containing_block_size, false);
243248
}
244249

245250
bool have_parent() const
@@ -272,9 +277,9 @@ namespace litehtml
272277
return !(m_skip || src_el()->css().get_display() == display_none || src_el()->css().get_visibility() != visibility_visible);
273278
}
274279

275-
int calc_width(int defVal) const;
276-
bool get_predefined_height(int& p_height) const;
277-
void apply_relative_shift(int parent_width);
280+
int calc_width(int defVal, int containing_block_width) const;
281+
bool get_predefined_height(int& p_height, int containing_block_height) const;
282+
void apply_relative_shift(const containing_block_context &containing_block_size);
278283
void calc_outlines( int parent_width );
279284
void calc_auto_margins(int parent_width);
280285

@@ -334,7 +339,7 @@ namespace litehtml
334339
int_int_cache m_cache_line_left;
335340
int_int_cache m_cache_line_right;
336341

337-
int _render(int x, int y, int max_width, bool second_pass) override;
342+
int _render(int x, int y, int max_width, const containing_block_context &containing_block_size, bool second_pass) override;
338343

339344
/**
340345
* Render block content.
@@ -346,9 +351,9 @@ namespace litehtml
346351
* @param ret_width - input minimal width.
347352
* @return return value is the minimal width of the content in block. Must be greater or equal to ret_width parameter
348353
*/
349-
virtual int _render_content(int x, int y, int max_width, bool second_pass, int ret_width) {return ret_width;}
354+
virtual int _render_content(int x, int y, int max_width, bool second_pass, int ret_width, const containing_block_context &containing_block_size) {return ret_width;}
350355

351-
int place_float(const std::shared_ptr<render_item> &el, int top, int max_width);
356+
int place_float(const std::shared_ptr<render_item> &el, int top, int max_width, const containing_block_context &containing_block_size);
352357
int get_floats_height(element_float el_float = float_none) const override;
353358
int get_left_floats_height() const override;
354359
int get_right_floats_height() const override;
@@ -358,7 +363,9 @@ namespace litehtml
358363
void add_float(const std::shared_ptr<render_item> &el, int x, int y) override;
359364
int get_cleared_top(const std::shared_ptr<render_item> &el, int line_top) const;
360365
int find_next_line_top( int top, int width, int def_right ) override;
361-
virtual void fix_line_width( int max_width, element_float flt ) {}
366+
virtual void fix_line_width(int max_width, element_float flt,
367+
const containing_block_context &containing_block_size)
368+
{}
362369
void update_floats(int dy, const std::shared_ptr<render_item> &_parent) override;
363370
public:
364371
explicit render_item_block(std::shared_ptr<element> src_el) : render_item(std::move(src_el))
@@ -379,7 +386,8 @@ namespace litehtml
379386
class render_item_block_context : public render_item_block
380387
{
381388
protected:
382-
int _render_content(int x, int y, int max_width, bool second_pass, int ret_width) override;
389+
int _render_content(int x, int y, int max_width, bool second_pass, int ret_width,
390+
const containing_block_context &containing_block_size) override;
383391

384392
public:
385393
explicit render_item_block_context(std::shared_ptr<element> src_el) : render_item_block(std::move(src_el))
@@ -417,12 +425,14 @@ namespace litehtml
417425
std::vector<std::unique_ptr<litehtml::line_box> > m_line_boxes;
418426
int m_max_line_width;
419427

420-
int _render_content(int x, int y, int max_width, bool second_pass, int ret_width) override;
421-
void fix_line_width( int max_width, element_float flt ) override;
428+
int _render_content(int x, int y, int max_width, bool second_pass, int ret_width,
429+
const containing_block_context &containing_block_size) override;
430+
void fix_line_width(int max_width, element_float flt,
431+
const containing_block_context &containing_block_size) override;
422432

423-
std::list<std::unique_ptr<line_box_item> > finish_last_box(bool end_of_render, int max_width);
424-
void place_inline(std::unique_ptr<line_box_item> item, int max_width);
425-
int new_box(const std::unique_ptr<line_box_item>& el, int max_width, line_context& line_ctx);
433+
std::list<std::unique_ptr<line_box_item> > finish_last_box(bool end_of_render, int max_width, const containing_block_context &containing_block_size);
434+
void place_inline(std::unique_ptr<line_box_item> item, int max_width, const containing_block_context &containing_block_size);
435+
int new_box(const std::unique_ptr<line_box_item>& el, int max_width, line_context& line_ctx, const containing_block_context &containing_block_size);
426436
void apply_vertical_align() override;
427437
public:
428438
explicit render_item_inline_context(std::shared_ptr<element> src_el) : render_item_block(std::move(src_el)), m_max_line_width(0)
@@ -444,7 +454,7 @@ namespace litehtml
444454
int m_border_spacing_x;
445455
int m_border_spacing_y;
446456

447-
int _render(int x, int y, int max_width, bool second_pass) override;
457+
int _render(int x, int y, int max_width, const containing_block_context &containing_block_size, bool second_pass) override;
448458

449459
public:
450460
explicit render_item_table(std::shared_ptr<element> src_el);
@@ -464,7 +474,7 @@ namespace litehtml
464474
explicit render_item_table_part(std::shared_ptr<element> src_el) : render_item(std::move(src_el))
465475
{}
466476

467-
int _render(int x, int y, int max_width, bool second_pass) override
477+
int _render(int x, int y, int max_width, const containing_block_context &containing_block_size, bool second_pass) override
468478
{return 0;}
469479
std::shared_ptr<render_item> clone() override
470480
{
@@ -478,7 +488,7 @@ namespace litehtml
478488
explicit render_item_table_row(std::shared_ptr<element> src_el) : render_item(std::move(src_el))
479489
{}
480490

481-
int _render(int x, int y, int max_width, bool second_pass) override
491+
int _render(int x, int y, int max_width, const containing_block_context &containing_block_size, bool second_pass) override
482492
{return 0;}
483493
std::shared_ptr<render_item> clone() override
484494
{
@@ -492,7 +502,7 @@ namespace litehtml
492502
protected:
493503
position::vector m_boxes;
494504

495-
int _render(int x, int y, int max_width, bool second_pass) override;
505+
int _render(int x, int y, int max_width, const containing_block_context &containing_block_size, bool second_pass) override;
496506
public:
497507
explicit render_item_inline(std::shared_ptr<element> src_el) : render_item(std::move(src_el))
498508
{}
@@ -512,8 +522,8 @@ namespace litehtml
512522
class render_item_image : public render_item
513523
{
514524
protected:
515-
int _render(int x, int y, int max_width, bool second_pass) override;
516-
int calc_max_height(int image_height);
525+
int _render(int x, int y, int max_width, const containing_block_context &containing_block_size, bool second_pass) override;
526+
int calc_max_height(int image_height, int containing_block_height);
517527

518528
public:
519529
explicit render_item_image(std::shared_ptr<element> src_el) : render_item(std::move(src_el))
@@ -548,7 +558,8 @@ namespace litehtml
548558
protected:
549559
std::list<std::unique_ptr<flex_item>> m_flex_items;
550560

551-
int _render_content(int x, int y, int max_width, bool second_pass, int ret_width) override;
561+
int _render_content(int x, int y, int max_width, bool second_pass, int ret_width,
562+
const containing_block_context &containing_block_size) override;
552563

553564
public:
554565
explicit render_item_flex(std::shared_ptr<element> src_el) : render_item_block(std::move(src_el))

include/litehtml/types.h

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ namespace litehtml
4545
int width;
4646
int height;
4747

48-
size()
48+
size(int w, int h) : width(w), height(h)
49+
{
50+
}
51+
52+
size() : width(0), height(0)
4953
{
50-
width = 0;
51-
height = 0;
5254
}
5355
};
5456

@@ -182,6 +184,46 @@ namespace litehtml
182184
draw_positioned,
183185
};
184186

187+
struct containing_block_context
188+
{
189+
enum cbc_value_type
190+
{
191+
cbc_value_type_absolute, // width/height of containing block is defined as absolute value
192+
cbc_value_type_percentage, // width/height of containing block is defined as percentage
193+
cbc_value_type_auto, // width/height of containing block is defined as auto
194+
cbc_value_type_none, // min/max width/height of containing block is defined as none
195+
};
196+
197+
int width; // width of the containing block
198+
cbc_value_type width_type;
199+
int min_width;
200+
cbc_value_type min_width_type;
201+
int max_width;
202+
cbc_value_type max_width_type;
203+
204+
int height; // height of the containing block
205+
cbc_value_type height_type;
206+
int min_height;
207+
cbc_value_type min_height_type;
208+
int max_height;
209+
cbc_value_type max_height_type;
210+
211+
containing_block_context() :
212+
width(0),
213+
width_type(cbc_value_type_auto),
214+
min_width(0),
215+
min_width_type(cbc_value_type_none),
216+
max_width(0),
217+
max_width_type(cbc_value_type_none),
218+
height(0),
219+
height_type(cbc_value_type_auto),
220+
min_height(0),
221+
min_height_type(cbc_value_type_none),
222+
max_height(0),
223+
max_height_type(cbc_value_type_none)
224+
{}
225+
};
226+
185227
#define style_display_strings "none;block;inline;inline-block;inline-table;list-item;table;table-caption;table-cell;table-column;table-column-group;table-footer-group;table-header-group;table-row;table-row-group;inline-text;flex;inline-flex"
186228

187229
enum style_display

src/document.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,13 +296,21 @@ int litehtml::document::render( int max_width, render_type rt )
296296
int ret = 0;
297297
if(m_root)
298298
{
299+
position client_rc;
300+
m_container->get_client_rect(client_rc);
301+
containing_block_context cb_context;
302+
cb_context.width = client_rc.width;
303+
cb_context.width_type = containing_block_context::cbc_value_type_absolute;
304+
cb_context.height = client_rc.height;
305+
cb_context.height_type = containing_block_context::cbc_value_type_absolute;
306+
299307
if(rt == render_fixed_only)
300308
{
301309
m_fixed_boxes.clear();
302310
m_root_render->render_positioned(rt);
303311
} else
304312
{
305-
ret = m_root_render->render(0, 0, max_width);
313+
ret = m_root_render->render(0, 0, max_width, cb_context);
306314
if(m_root_render->fetch_positioned())
307315
{
308316
m_fixed_boxes.clear();

src/line_box.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ int litehtml::line_box::calc_va_baseline(const va_context& current, vertical_ali
191191
}
192192
}
193193

194-
std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish(bool last_box)
194+
std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish(bool last_box, const containing_block_context &containing_block_size)
195195
{
196196
std::list< std::unique_ptr<line_box_item> > ret_items;
197197

@@ -272,8 +272,6 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish
272272
return ret_items;
273273
}
274274

275-
m_min_width = m_items.back()->right();
276-
277275
int spc_x = 0;
278276

279277
int add_x = 0;
@@ -317,8 +315,11 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish
317315
current_context.baseline = 0;
318316
current_context.fm = m_font_metrics;
319317

318+
m_min_width = 0;
319+
320320
for (const auto& lbi : m_items)
321321
{
322+
m_min_width += lbi->get_rendered_min_width();
322323
{ // start text_align_justify
323324
if (spc_x && counter)
324325
{
@@ -487,7 +488,7 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish
487488
lbi->pos().y = m_top + m_height - lbi->get_el()->height() + lbi->get_el()->content_offset_top();
488489
}
489490
}
490-
lbi->get_el()->apply_relative_shift(m_right - m_left);
491+
lbi->get_el()->apply_relative_shift(containing_block_size);
491492

492493
// Calculate and push inline box into the render item element
493494
if(lbi->get_type() == line_box_item::type_inline_start || lbi->get_type() == line_box_item::type_inline_continue)
@@ -513,7 +514,7 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish
513514

514515
for(auto iter = inlines.rbegin(); iter != inlines.rend(); ++iter)
515516
{
516-
iter->box.width = m_min_width - iter->box.x;
517+
iter->box.width = m_items.back()->right() - iter->box.x;
517518
iter->element->add_inline_box(iter->box);
518519

519520
ret_items.emplace_front(std::unique_ptr<line_box_item>(new lbi_continue(iter->element)));

0 commit comments

Comments
 (0)