@@ -70,6 +70,12 @@ internal class CssBox : CssBoxProperties, IDisposable
7070 /// Flag that indicates that CssTable algorithm already made fixes on it.
7171 /// </remarks>
7272 internal bool _tableFixed ;
73+
74+ /// <summary>
75+ /// Flag indicating that we're on a second pass for laying out the element after
76+ /// avoiding a page break.
77+ /// </summary>
78+ internal bool _pageBreakAvoided ;
7379
7480 protected bool _wordsSizeMeasured ;
7581 private CssBox _listItemBox ;
@@ -651,7 +657,9 @@ protected virtual async Task PerformLayoutImpAsync(RGraphics g)
651657 Size = new RSize ( width - ActualMarginLeft - ActualMarginRight , Size . Height ) ;
652658 }
653659
654- if ( Display != CssConstants . TableCell )
660+ // Don't recalculate the element's position if we're
661+ // on our second pass after avoiding a page break.
662+ if ( Display != CssConstants . TableCell && ! _pageBreakAvoided )
655663 {
656664 double left ;
657665 double top ;
@@ -700,15 +708,6 @@ protected virtual async Task PerformLayoutImpAsync(RGraphics g)
700708 {
701709 this . BreakPage ( true ) ;
702710 }
703- else if ( this . PageBreakInside == CssConstants . Avoid && prevSibling != null )
704- {
705- // handle page break avoiding.
706- var pageLocationY = Location . Y % HtmlContainer . PageSize . Height ;
707- if ( ActualHeight + pageLocationY > HtmlContainer . PageSize . Height )
708- {
709- this . BreakPage ( true ) ;
710- }
711- }
712711
713712 //Start with the assumption this is zero height.
714713 ActualBottom = Location . Y ;
@@ -754,6 +753,27 @@ protected virtual async Task PerformLayoutImpAsync(RGraphics g)
754753
755754 if ( ! IsFixed && ! IsAbsolute )
756755 {
756+ if ( PageBreakInside == CssConstants . Avoid
757+ && prevSibling != null
758+ && Display != CssConstants . TableCell
759+ && ! _pageBreakAvoided )
760+ {
761+ // handle page break avoiding.
762+ var pageLocationY = Location . Y % HtmlContainer . PageSize . Height ;
763+ if ( Size . Height + pageLocationY > HtmlContainer . PageSize . Height )
764+ {
765+ // if we break page, we'll do another pass at PerformLayoutAsync
766+ // so that child elements are re-positioned correctly.
767+ BreakPage ( true ) ;
768+ _pageBreakAvoided = true ;
769+ await this . PerformLayoutAsync ( g ) ;
770+
771+ // We'll set this flag back to false as this element
772+ // might need re-positioning by its parent.
773+ _pageBreakAvoided = false ;
774+ }
775+ }
776+
757777 var actualWidth = Math . Max ( GetMinimumWidth ( ) + GetWidthMarginDeep ( this ) , Size . Width < 90999 ? ActualRight - HtmlContainer . Root . Location . X : 0 ) ;
758778 HtmlContainer . ActualSize = CommonUtils . Max ( HtmlContainer . ActualSize , new RSize ( actualWidth , ActualBottom - HtmlContainer . Root . Location . Y ) ) ;
759779 }
0 commit comments