bool NextElementsDontFit(int idx, Area remainingArea, XUnit previousMarginBottom) { XUnit elementDistance = previousMarginBottom; Area area = remainingArea; for (int index = idx + 1; index < _elements.Count; ++index) { // Never combine more than MaxCombineElements elements if (index - idx > MaxCombineElements) { return(false); } DocumentObject obj = _elements[index]; Renderer currRenderer = Renderer.Create(_gfx, _documentRenderer, obj, _areaProvider.AreaFieldInfos); elementDistance = MarginMax(elementDistance, currRenderer.InitialLayoutInfo.MarginTop); area = area.Lower(elementDistance); if (area.Height <= 0) { return(true); } currRenderer.Format(area, null); FormatInfo currFormatInfo = currRenderer.RenderInfo.FormatInfo; LayoutInfo currLayoutInfo = currRenderer.RenderInfo.LayoutInfo; if (currLayoutInfo.VerticalReference != VerticalReference.PreviousElement) { return(false); } if (!currFormatInfo.StartingIsComplete) { return(true); } if (currLayoutInfo.KeepTogether && !currFormatInfo.IsComplete) { return(true); } if (!(currLayoutInfo.KeepTogether && currLayoutInfo.KeepWithNext)) { return(false); } area = area.Lower(currLayoutInfo.ContentArea.Height); if (area.Height <= 0) { return(true); } elementDistance = currLayoutInfo.MarginBottom; } return(false); }
/// <summary> /// Indicates that a break between areas has to be performed before the element with the given idx. /// </summary> /// <param name="idx">Index of the document element.</param> /// <param name="renderer">A formatted renderer for the document element.</param> /// <param name="remainingArea">The remaining area.</param> bool IsForcedAreaBreak(int idx, Renderer renderer, Area remainingArea) { FormatInfo formatInfo = renderer.RenderInfo.FormatInfo; LayoutInfo layoutInfo = renderer.RenderInfo.LayoutInfo; if (formatInfo.IsStarting && !formatInfo.StartingIsComplete) { return(true); } if (layoutInfo.KeepTogether && !formatInfo.IsComplete) { return(true); } if (layoutInfo.KeepTogether && layoutInfo.KeepWithNext) { Area area = remainingArea.Lower(layoutInfo.ContentArea.Height); return(NextElementsDontFit(idx, area, layoutInfo.MarginBottom)); } return(false); }
bool NeedsEndingOnNextArea(int idx, Renderer renderer, Area remainingArea, bool isFirstOnPage) { LayoutInfo layoutInfo = renderer.RenderInfo.LayoutInfo; if (isFirstOnPage && layoutInfo.KeepTogether) { return(false); } FormatInfo formatInfo = renderer.RenderInfo.FormatInfo; if (!formatInfo.EndingIsComplete) { return(false); } if (layoutInfo.KeepWithNext) { remainingArea = remainingArea.Lower(layoutInfo.ContentArea.Height); return(NextElementsDontFit(idx, remainingArea, layoutInfo.MarginBottom)); } return(false); }
/// <summary> /// Formats the elements on the areas provided by the area provider. /// </summary> /// <param name="gfx">The graphics object to render on.</param> /// <param name="topLevel">if set to <c>true</c> formats the object is on top level.</param> public void FormatOnAreas(XGraphics gfx, bool topLevel) { _gfx = gfx; XUnit prevBottomMargin = 0; XUnit yPos = prevBottomMargin; RenderInfo prevRenderInfo = null; FormatInfo prevFormatInfo = null; List <RenderInfo> renderInfos = new List <RenderInfo>(); bool ready = _elements.Count == 0; bool isFirstOnPage = true; Area area = _areaProvider.GetNextArea(); XUnit maxHeight = area.Height; if (ready) { _areaProvider.StoreRenderInfos(renderInfos); return; } int idx = 0; while (!ready && area != null) { DocumentObject docObj = _elements[idx]; Renderer renderer = Renderer.Create(gfx, _documentRenderer, docObj, _areaProvider.AreaFieldInfos); if (renderer != null) // "Slightly hacked" for legends: see below { renderer.MaxElementHeight = maxHeight; } if (topLevel && _documentRenderer.HasPrepareDocumentProgress) { _documentRenderer.OnPrepareDocumentProgress(_documentRenderer.ProgressCompleted + idx + 1, _documentRenderer.ProgressMaximum); } // "Slightly hacked" for legends: they are rendered as part of the chart. // So they are skipped here. if (renderer == null) { ready = idx == _elements.Count - 1; if (ready) { _areaProvider.StoreRenderInfos(renderInfos); } ++idx; continue; } /////////////////////////////////////////// if (prevFormatInfo == null) { LayoutInfo initialLayoutInfo = renderer.InitialLayoutInfo; XUnit distance = prevBottomMargin; if (initialLayoutInfo.VerticalReference == VerticalReference.PreviousElement && initialLayoutInfo.Floating != Floating.None) { distance = MarginMax(initialLayoutInfo.MarginTop, distance); } area = area.Lower(distance); } renderer.Format(area, prevFormatInfo); _areaProvider.PositionHorizontally(renderer.RenderInfo.LayoutInfo); bool pagebreakBefore = _areaProvider.IsAreaBreakBefore(renderer.RenderInfo.LayoutInfo) && !isFirstOnPage; pagebreakBefore = pagebreakBefore || !isFirstOnPage && IsForcedAreaBreak(idx, renderer, area); if (!pagebreakBefore && renderer.RenderInfo.FormatInfo.IsEnding) { if (PreviousRendererNeedsRemoveEnding(prevRenderInfo, renderer.RenderInfo, area)) { prevRenderInfo.RemoveEnding(); renderer = Renderer.Create(gfx, _documentRenderer, docObj, _areaProvider.AreaFieldInfos); renderer.MaxElementHeight = maxHeight; renderer.Format(area, prevRenderInfo.FormatInfo); } else if (NeedsEndingOnNextArea(idx, renderer, area, isFirstOnPage)) { renderer.RenderInfo.RemoveEnding(); prevRenderInfo = FinishPage(renderer.RenderInfo, pagebreakBefore, ref renderInfos); if (prevRenderInfo != null) { prevFormatInfo = prevRenderInfo.FormatInfo; } else { prevFormatInfo = null; isFirstOnPage = true; } prevBottomMargin = 0; area = _areaProvider.GetNextArea(); maxHeight = area.Height; } else { renderInfos.Add(renderer.RenderInfo); isFirstOnPage = false; _areaProvider.PositionVertically(renderer.RenderInfo.LayoutInfo); if (renderer.RenderInfo.LayoutInfo.VerticalReference == VerticalReference.PreviousElement && renderer.RenderInfo.LayoutInfo.Floating != Floating.None) { prevBottomMargin = renderer.RenderInfo.LayoutInfo.MarginBottom; if (renderer.RenderInfo.LayoutInfo.Floating != Floating.None) { area = area.Lower(renderer.RenderInfo.LayoutInfo.ContentArea.Height); } } else { prevBottomMargin = 0; } prevFormatInfo = null; prevRenderInfo = null; ++idx; } } else { if (renderer.RenderInfo.FormatInfo.IsEmpty && isFirstOnPage) { area = area.Unite(new Rectangle(area.X, area.Y, area.Width, double.MaxValue)); renderer = Renderer.Create(gfx, _documentRenderer, docObj, _areaProvider.AreaFieldInfos); renderer.MaxElementHeight = maxHeight; renderer.Format(area, prevFormatInfo); prevFormatInfo = null; _areaProvider.PositionHorizontally(renderer.RenderInfo.LayoutInfo); _areaProvider.PositionVertically(renderer.RenderInfo.LayoutInfo); ready = idx == _elements.Count - 1; ++idx; } prevRenderInfo = FinishPage(renderer.RenderInfo, pagebreakBefore, ref renderInfos); if (prevRenderInfo != null) { prevFormatInfo = prevRenderInfo.FormatInfo; } else { prevFormatInfo = null; } isFirstOnPage = true; prevBottomMargin = 0; if (!ready) { area = _areaProvider.GetNextArea(); maxHeight = area.Height; } } if (idx == _elements.Count && !ready) { _areaProvider.StoreRenderInfos(renderInfos); ready = true; } } }
bool NeedsEndingOnNextArea(int idx, Renderer renderer, Area remainingArea, bool isFirstOnPage) { LayoutInfo layoutInfo = renderer.RenderInfo.LayoutInfo; if (isFirstOnPage && layoutInfo.KeepTogether) return false; FormatInfo formatInfo = renderer.RenderInfo.FormatInfo; if (!formatInfo.EndingIsComplete) return false; if (layoutInfo.KeepWithNext) { remainingArea = remainingArea.Lower(layoutInfo.ContentArea.Height); return NextElementsDontFit(idx, remainingArea, layoutInfo.MarginBottom); } return false; }
/// <summary> /// Indicates that a break between areas has to be performed before the element with the given idx. /// </summary> /// <param name="idx">Index of the document element.</param> /// <param name="renderer">A formatted renderer for the document element.</param> /// <param name="remainingArea">The remaining area.</param> bool IsForcedAreaBreak(int idx, Renderer renderer, Area remainingArea) { FormatInfo formatInfo = renderer.RenderInfo.FormatInfo; LayoutInfo layoutInfo = renderer.RenderInfo.LayoutInfo; if (formatInfo.IsStarting && !formatInfo.StartingIsComplete) return true; if (layoutInfo.KeepTogether && !formatInfo.IsComplete) return true; if (layoutInfo.KeepTogether && layoutInfo.KeepWithNext) { Area area = remainingArea.Lower(layoutInfo.ContentArea.Height); return NextElementsDontFit(idx, area, layoutInfo.MarginBottom); } return false; }