2019-06-15 23:41:15 +02:00
# include <LibHTML/DOM/Element.h>
# include <LibHTML/Layout/LayoutBlock.h>
2019-06-15 22:49:44 +02:00
2019-09-21 15:32:17 +03:00
LayoutBlock : : LayoutBlock ( const Node * node , StyleProperties & & style_properties )
: LayoutNode ( node , move ( style_properties ) )
2019-06-15 22:49:44 +02:00
{
}
LayoutBlock : : ~ LayoutBlock ( )
{
}
2019-06-20 23:00:26 +02:00
2019-07-08 17:42:23 +02:00
LayoutNode & LayoutBlock : : inline_wrapper ( )
{
2019-09-25 11:56:16 +03:00
if ( ! last_child ( ) | | ! last_child ( ) - > is_block ( ) | | last_child ( ) - > node ( ) ! = nullptr ) {
2019-09-21 15:32:17 +03:00
append_child ( adopt ( * new LayoutBlock ( nullptr , { } ) ) ) ;
2019-07-08 17:42:23 +02:00
}
return * last_child ( ) ;
}
2019-06-20 23:00:26 +02:00
void LayoutBlock : : layout ( )
{
2019-07-01 07:28:37 +02:00
compute_width ( ) ;
2019-08-18 08:37:53 +02:00
compute_position ( ) ;
int content_height = 0 ;
for_each_child ( [ & ] ( auto & child ) {
child . layout ( ) ;
content_height + = child . rect ( ) . height ( )
+ child . style ( ) . margin ( ) . top . to_px ( )
+ child . style ( ) . border ( ) . top . to_px ( )
+ child . style ( ) . padding ( ) . top . to_px ( )
+ child . style ( ) . margin ( ) . bottom . to_px ( )
+ child . style ( ) . border ( ) . bottom . to_px ( )
+ child . style ( ) . padding ( ) . bottom . to_px ( ) ;
} ) ;
rect ( ) . set_height ( content_height ) ;
2019-06-20 23:00:26 +02:00
2019-07-01 07:28:37 +02:00
compute_height ( ) ;
}
void LayoutBlock : : compute_width ( )
{
2019-09-21 15:32:17 +03:00
auto & style_properties = this - > style_properties ( ) ;
2019-07-24 07:34:07 +02:00
2019-08-18 08:09:56 +02:00
auto auto_value = Length ( ) ;
auto zero_value = Length ( 0 , Length : : Type : : Absolute ) ;
2019-09-21 15:32:17 +03:00
auto width = style_properties . length_or_fallback ( " width " , auto_value ) ;
auto margin_left = style_properties . length_or_fallback ( " margin-left " , zero_value ) ;
auto margin_right = style_properties . length_or_fallback ( " margin-right " , zero_value ) ;
auto border_left = style_properties . length_or_fallback ( " border-left " , zero_value ) ;
auto border_right = style_properties . length_or_fallback ( " border-right " , zero_value ) ;
auto padding_left = style_properties . length_or_fallback ( " padding-left " , zero_value ) ;
auto padding_right = style_properties . length_or_fallback ( " padding-right " , zero_value ) ;
2019-07-24 07:34:07 +02:00
2019-08-18 08:09:56 +02:00
dbg ( ) < < " Left: " < < margin_left < < " + " < < border_left < < " + " < < padding_left ;
dbg ( ) < < " Right: " < < margin_right < < " + " < < border_right < < " + " < < padding_right ;
2019-07-26 08:05:14 +02:00
int total_px = 0 ;
for ( auto & value : { margin_left , border_left , padding_left , width , padding_right , border_right , margin_right } ) {
2019-08-18 08:09:56 +02:00
total_px + = value . to_px ( ) ;
2019-07-26 08:05:14 +02:00
}
dbg ( ) < < " Total: " < < total_px ;
// 10.3.3 Block-level, non-replaced elements in normal flow
// If 'width' is not 'auto' and 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' (plus any of 'margin-left' or 'margin-right' that are not 'auto') is larger than the width of the containing block, then any 'auto' values for 'margin-left' or 'margin-right' are, for the following rules, treated as zero.
2019-08-18 08:09:56 +02:00
if ( width . is_auto ( ) & & total_px > containing_block ( ) - > rect ( ) . width ( ) ) {
if ( margin_left . is_auto ( ) )
2019-07-26 08:05:14 +02:00
margin_left = zero_value ;
2019-08-18 08:09:56 +02:00
if ( margin_right . is_auto ( ) )
2019-07-26 08:05:14 +02:00
margin_right = zero_value ;
}
2019-08-18 08:09:56 +02:00
// 10.3.3 cont'd.
auto underflow_px = containing_block ( ) - > rect ( ) . width ( ) - total_px ;
if ( width . is_auto ( ) ) {
if ( margin_left . is_auto ( ) )
margin_left = zero_value ;
if ( margin_right . is_auto ( ) )
margin_right = zero_value ;
if ( underflow_px > = 0 ) {
width = Length ( underflow_px , Length : : Type : : Absolute ) ;
} else {
width = zero_value ;
margin_right = Length ( margin_right . to_px ( ) + underflow_px , Length : : Type : : Absolute ) ;
}
} else {
if ( ! margin_left . is_auto ( ) & & ! margin_right . is_auto ( ) ) {
margin_right = Length ( margin_right . to_px ( ) + underflow_px , Length : : Type : : Absolute ) ;
} else if ( ! margin_left . is_auto ( ) & & margin_right . is_auto ( ) ) {
margin_right = Length ( underflow_px , Length : : Type : : Absolute ) ;
} else if ( margin_left . is_auto ( ) & & ! margin_right . is_auto ( ) ) {
margin_left = Length ( underflow_px , Length : : Type : : Absolute ) ;
} else { // margin_left.is_auto() && margin_right.is_auto()
auto half_of_the_underflow = Length ( underflow_px / 2 , Length : : Type : : Absolute ) ;
margin_left = half_of_the_underflow ;
margin_right = half_of_the_underflow ;
}
}
rect ( ) . set_width ( width . to_px ( ) ) ;
style ( ) . margin ( ) . left = margin_left ;
style ( ) . margin ( ) . right = margin_right ;
style ( ) . border ( ) . left = border_left ;
style ( ) . border ( ) . right = border_right ;
style ( ) . padding ( ) . left = padding_left ;
style ( ) . padding ( ) . right = padding_right ;
2019-07-01 07:28:37 +02:00
}
2019-08-18 08:37:53 +02:00
void LayoutBlock : : compute_position ( )
{
2019-09-21 15:32:17 +03:00
auto & style_properties = this - > style_properties ( ) ;
2019-08-18 08:37:53 +02:00
auto auto_value = Length ( ) ;
auto zero_value = Length ( 0 , Length : : Type : : Absolute ) ;
2019-09-21 15:32:17 +03:00
auto width = style_properties . length_or_fallback ( " width " , auto_value ) ;
style ( ) . margin ( ) . top = style_properties . length_or_fallback ( " margin-top " , zero_value ) ;
style ( ) . margin ( ) . bottom = style_properties . length_or_fallback ( " margin-bottom " , zero_value ) ;
style ( ) . border ( ) . top = style_properties . length_or_fallback ( " border-top " , zero_value ) ;
style ( ) . border ( ) . bottom = style_properties . length_or_fallback ( " border-bottom " , zero_value ) ;
style ( ) . padding ( ) . top = style_properties . length_or_fallback ( " padding-top " , zero_value ) ;
style ( ) . padding ( ) . bottom = style_properties . length_or_fallback ( " padding-bottom " , zero_value ) ;
2019-08-18 08:37:53 +02:00
rect ( ) . set_x ( containing_block ( ) - > rect ( ) . x ( ) + style ( ) . margin ( ) . left . to_px ( ) + style ( ) . border ( ) . left . to_px ( ) + style ( ) . padding ( ) . left . to_px ( ) ) ;
rect ( ) . set_y ( containing_block ( ) - > rect ( ) . y ( ) + style ( ) . margin ( ) . top . to_px ( ) + style ( ) . border ( ) . top . to_px ( ) + style ( ) . padding ( ) . top . to_px ( ) ) ;
}
2019-07-01 07:28:37 +02:00
void LayoutBlock : : compute_height ( )
{
2019-09-21 15:32:17 +03:00
auto & style_properties = this - > style_properties ( ) ;
auto height_property = style_properties . property ( " height " ) ;
2019-08-18 08:37:53 +02:00
if ( ! height_property . has_value ( ) )
return ;
auto height_length = height_property . value ( ) - > to_length ( ) ;
if ( height_length . is_absolute ( ) )
rect ( ) . set_height ( height_length . to_px ( ) ) ;
2019-06-20 23:00:26 +02:00
}