diff --git a/Source/Demos/HtmlRenderer.Demo.Common/TestSamples/37. Breaking Pages 4 - Divs.htm b/Source/Demos/HtmlRenderer.Demo.Common/TestSamples/37. Breaking Pages 4 - Divs.htm index 8af74d192..b0c4ebeae 100644 --- a/Source/Demos/HtmlRenderer.Demo.Common/TestSamples/37. Breaking Pages 4 - Divs.htm +++ b/Source/Demos/HtmlRenderer.Demo.Common/TestSamples/37. Breaking Pages 4 - Divs.htm @@ -15,14 +15,14 @@
This is on page 4. -
+
This is also on page 4
-
- This is also on page 4. -
-
+
+ This is on page 4 +
+
This is on page 5
diff --git a/Source/Demos/HtmlRenderer.Demo.Console/Program.cs b/Source/Demos/HtmlRenderer.Demo.Console/Program.cs index 80e8c60b2..3b9f51e90 100644 --- a/Source/Demos/HtmlRenderer.Demo.Console/Program.cs +++ b/Source/Demos/HtmlRenderer.Demo.Console/Program.cs @@ -24,7 +24,7 @@ foreach (var htmlSample in samples) { ////Just doing one test here. Comment this for all of them. - if (!htmlSample.FullName.Contains("37")) continue; + if (!htmlSample.FullName.Contains("37") && !htmlSample.FullName.Contains("34")) continue; //await skia.GenerateSampleAsync(htmlSample); //await svgSkia.GenerateSampleAsync(htmlSample); diff --git a/Source/HtmlRenderer/Core/Dom/CssBox.cs b/Source/HtmlRenderer/Core/Dom/CssBox.cs index a940aa713..59579aef4 100644 --- a/Source/HtmlRenderer/Core/Dom/CssBox.cs +++ b/Source/HtmlRenderer/Core/Dom/CssBox.cs @@ -70,6 +70,12 @@ internal class CssBox : CssBoxProperties, IDisposable /// Flag that indicates that CssTable algorithm already made fixes on it. /// internal bool _tableFixed; + + /// + /// Flag indicating that we're on a second pass for laying out the element after + /// avoiding a page break. + /// + internal bool _pageBreakAvoided; protected bool _wordsSizeMeasured; private CssBox _listItemBox; @@ -651,7 +657,9 @@ protected virtual async Task PerformLayoutImpAsync(RGraphics g) Size = new RSize(width - ActualMarginLeft - ActualMarginRight, Size.Height); } - if (Display != CssConstants.TableCell) + // Don't recalculate the element's position if we're + // on our second pass after avoiding a page break. + if (Display != CssConstants.TableCell && !_pageBreakAvoided) { double left; double top; @@ -700,15 +708,6 @@ protected virtual async Task PerformLayoutImpAsync(RGraphics g) { this.BreakPage(true); } - else if (this.PageBreakInside == CssConstants.Avoid && prevSibling != null) - { - // handle page break avoiding. - var pageLocationY = Location.Y % HtmlContainer.PageSize.Height; - if (ActualHeight + pageLocationY > HtmlContainer.PageSize.Height) - { - this.BreakPage(true); - } - } //Start with the assumption this is zero height. ActualBottom = Location.Y; @@ -754,6 +753,27 @@ protected virtual async Task PerformLayoutImpAsync(RGraphics g) if (!IsFixed && !IsAbsolute) { + if (PageBreakInside == CssConstants.Avoid + && prevSibling != null + && Display != CssConstants.TableCell + && !_pageBreakAvoided) + { + // handle page break avoiding. + var pageLocationY = Location.Y % HtmlContainer.PageSize.Height; + if (Size.Height + pageLocationY > HtmlContainer.PageSize.Height) + { + // if we break page, we'll do another pass at PerformLayoutAsync + // so that child elements are re-positioned correctly. + BreakPage(true); + _pageBreakAvoided = true; + await this.PerformLayoutAsync(g); + + // We'll set this flag back to false as this element + // might need re-positioning by its parent. + _pageBreakAvoided = false; + } + } + var actualWidth = Math.Max(GetMinimumWidth() + GetWidthMarginDeep(this), Size.Width < 90999 ? ActualRight - HtmlContainer.Root.Location.X : 0); HtmlContainer.ActualSize = CommonUtils.Max(HtmlContainer.ActualSize, new RSize(actualWidth, ActualBottom - HtmlContainer.Root.Location.Y)); }