@@ -10,9 +10,7 @@ use crate::context::LayoutContext;
10
10
use crate :: dom:: NodeExt ;
11
11
use crate :: dom_traversal:: { Contents , NodeAndStyleInfo } ;
12
12
use crate :: formatting_contexts:: IndependentFormattingContext ;
13
- use crate :: fragment_tree:: {
14
- BoxFragment , CollapsedBlockMargins , CollapsedMargin , FloatFragment , Fragment ,
15
- } ;
13
+ use crate :: fragment_tree:: { BoxFragment , CollapsedBlockMargins , CollapsedMargin , FloatFragment } ;
16
14
use crate :: geom:: flow_relative:: { Rect , Vec2 } ;
17
15
use crate :: positioned:: PositioningContext ;
18
16
use crate :: style_ext:: { ComputedValuesExt , DisplayInside } ;
@@ -658,34 +656,9 @@ impl FloatBox {
658
656
layout_context : & LayoutContext ,
659
657
positioning_context : & mut PositioningContext ,
660
658
containing_block : & ContainingBlock ,
661
- mut sequential_layout_state : Option < & mut SequentialLayoutState > ,
662
- ) -> Fragment {
663
- let sequential_layout_state = sequential_layout_state
664
- . as_mut ( )
665
- . expect ( "Tried to lay out a float with no sequential placement state!" ) ;
666
-
667
- // Speculate that the float ceiling will be located at the current block position plus the
668
- // result of solving any margins we're building up. This is usually right, but it can be
669
- // incorrect if there are more in-flow collapsible margins yet to be seen. An example
670
- // showing when this can go wrong:
671
- //
672
- // <div style="margin: 5px"></div>
673
- // <div style="float: left"></div>
674
- // <div style="margin: 10px"></div>
675
- //
676
- // Assuming these are all in-flow, the float should be placed 10px down from the start, not
677
- // 5px, but we can't know that because we haven't seen the block after this float yet.
678
- //
679
- // FIXME(pcwalton): Implement the proper behavior when speculation fails. Either detect it
680
- // afterward and fix it up, or detect this situation ahead of time via lookahead and make
681
- // sure `current_margin` is accurate before calling this method.
682
- sequential_layout_state
683
- . floats
684
- . lower_ceiling ( sequential_layout_state. current_block_position_including_margins ( ) ) ;
685
-
659
+ ) -> BoxFragment {
686
660
let style = self . contents . style ( ) . clone ( ) ;
687
- let float_context = & mut sequential_layout_state. floats ;
688
- let box_fragment = positioning_context. layout_maybe_position_relative_fragment (
661
+ positioning_context. layout_maybe_position_relative_fragment (
689
662
layout_context,
690
663
containing_block,
691
664
& style,
@@ -696,7 +669,7 @@ impl FloatBox {
696
669
let margin = pbm. margin . auto_is ( || Length :: zero ( ) ) ;
697
670
let pbm_sums = & ( & pbm. padding + & pbm. border ) + & margin;
698
671
699
- let ( content_size, fragments ) ;
672
+ let ( content_size, children ) ;
700
673
match self . contents {
701
674
IndependentFormattingContext :: NonReplaced ( ref mut non_replaced) => {
702
675
// Calculate inline size.
@@ -739,7 +712,7 @@ impl FloatBox {
739
712
. block
740
713
. auto_is ( || independent_layout. content_block_size ) ,
741
714
} ;
742
- fragments = independent_layout. fragments ;
715
+ children = independent_layout. fragments ;
743
716
} ,
744
717
IndependentFormattingContext :: Replaced ( ref replaced) => {
745
718
// https://drafts.csswg.org/css2/#float-replaced-width
@@ -750,40 +723,32 @@ impl FloatBox {
750
723
None ,
751
724
& pbm,
752
725
) ;
753
- fragments = replaced
726
+ children = replaced
754
727
. contents
755
728
. make_fragments ( & replaced. style , content_size. clone ( ) ) ;
756
729
} ,
757
730
} ;
758
- let margin_box_start_corner = float_context. add_float ( & PlacementInfo {
759
- size : & content_size + & pbm_sums. sum ( ) ,
760
- side : FloatSide :: from_style ( & style) . expect ( "Float box wasn't floated!" ) ,
761
- clear : ClearSide :: from_style ( & style) ,
762
- } ) ;
763
731
764
732
let content_rect = Rect {
765
- start_corner : & margin_box_start_corner + & pbm_sums . start_offset ( ) ,
766
- size : content_size. clone ( ) ,
733
+ start_corner : Vec2 :: zero ( ) ,
734
+ size : content_size,
767
735
} ;
768
736
769
- // Clearance is handled internally by the float placement logic, so there's no need
770
- // to store it explicitly in the fragment.
771
- let clearance = Length :: zero ( ) ;
772
-
773
737
BoxFragment :: new (
774
738
self . contents . base_fragment_info ( ) ,
775
739
style. clone ( ) ,
776
- fragments ,
740
+ children ,
777
741
content_rect,
778
742
pbm. padding ,
779
743
pbm. border ,
780
744
margin,
781
- clearance,
745
+ // Clearance is handled internally by the float placement logic, so there's no need
746
+ // to store it explicitly in the fragment.
747
+ Length :: zero ( ) , // clearance
782
748
CollapsedBlockMargins :: zero ( ) ,
783
749
)
784
750
} ,
785
- ) ;
786
- Fragment :: Float ( box_fragment)
751
+ )
787
752
}
788
753
}
789
754
@@ -890,4 +855,52 @@ impl SequentialLayoutState {
890
855
pub ( crate ) fn adjoin_assign ( & mut self , margin : & CollapsedMargin ) {
891
856
self . current_margin . adjoin_assign ( margin)
892
857
}
858
+
859
+ /// Get the offset of the current containing block and any uncollapsed margins.
860
+ pub ( crate ) fn current_containing_block_offset ( & self ) -> CSSPixelLength {
861
+ self . floats . containing_block_info . block_start +
862
+ self . floats
863
+ . containing_block_info
864
+ . block_start_margins_not_collapsed
865
+ . solve ( )
866
+ }
867
+
868
+ /// This function places a Fragment that has been created for a FloatBox.
869
+ pub ( crate ) fn place_float_fragment (
870
+ & mut self ,
871
+ box_fragment : & mut BoxFragment ,
872
+ margins_collapsing_with_parent_containing_block : CollapsedMargin ,
873
+ block_offset_from_containining_block_top : CSSPixelLength ,
874
+ ) {
875
+ let block_start_of_containing_block_in_bfc = self . floats . containing_block_info . block_start +
876
+ self . floats
877
+ . containing_block_info
878
+ . block_start_margins_not_collapsed
879
+ . adjoin ( & margins_collapsing_with_parent_containing_block)
880
+ . solve ( ) ;
881
+
882
+ self . floats . lower_ceiling (
883
+ block_start_of_containing_block_in_bfc + block_offset_from_containining_block_top,
884
+ ) ;
885
+
886
+ let pbm_sums = & ( & box_fragment. padding + & box_fragment. border ) + & box_fragment. margin ;
887
+ let margin_box_start_corner = self . floats . add_float ( & PlacementInfo {
888
+ size : & box_fragment. content_rect . size + & pbm_sums. sum ( ) ,
889
+ side : FloatSide :: from_style ( & box_fragment. style ) . expect ( "Float box wasn't floated!" ) ,
890
+ clear : ClearSide :: from_style ( & box_fragment. style ) ,
891
+ } ) ;
892
+
893
+ // This is the position of the float in the float-containing block formatting context. We add the
894
+ // existing start corner here because we may have already gotten some relative positioning offset.
895
+ let new_position_in_bfc = & ( & margin_box_start_corner + & pbm_sums. start_offset ( ) ) +
896
+ & box_fragment. content_rect . start_corner ;
897
+
898
+ // This is the position of the float relative to the containing block start.
899
+ let new_position_in_containing_block = Vec2 {
900
+ inline : new_position_in_bfc. inline - self . floats . containing_block_info . inline_start ,
901
+ block : new_position_in_bfc. block - block_start_of_containing_block_in_bfc,
902
+ } ;
903
+
904
+ box_fragment. content_rect . start_corner = new_position_in_containing_block;
905
+ }
893
906
}
0 commit comments