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;
                }
            }
        }
Пример #5
0
        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;
        }
Пример #6
0
        /// <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;
        }