예제 #1
0
        public override void AddChild(IRenderer renderer)
        {
            LayoutTaggingHelper taggingHelper = this.GetProperty <LayoutTaggingHelper>(Property.TAGGING_HELPER);

            if (taggingHelper != null)
            {
                LayoutTaggingHelper.AddTreeHints(taggingHelper, renderer);
            }
            // Some positioned renderers might have been fetched from non-positioned child and added to this renderer,
            // so we use this generic mechanism of determining which renderers have been just added.
            int numberOfChildRenderers           = childRenderers.Count;
            int numberOfPositionedChildRenderers = positionedRenderers.Count;

            base.AddChild(renderer);
            IList <IRenderer> addedRenderers           = new List <IRenderer>(1);
            IList <IRenderer> addedPositionedRenderers = new List <IRenderer>(1);

            while (childRenderers.Count > numberOfChildRenderers)
            {
                addedRenderers.Add(childRenderers[numberOfChildRenderers]);
                childRenderers.JRemoveAt(numberOfChildRenderers);
            }
            while (positionedRenderers.Count > numberOfPositionedChildRenderers)
            {
                addedPositionedRenderers.Add(positionedRenderers[numberOfPositionedChildRenderers]);
                positionedRenderers.JRemoveAt(numberOfPositionedChildRenderers);
            }
            bool marginsCollapsingEnabled = true.Equals(GetPropertyAsBoolean(Property.COLLAPSING_MARGINS));

            if (currentArea == null)
            {
                UpdateCurrentAndInitialArea(null);
                if (marginsCollapsingEnabled)
                {
                    marginsCollapseHandler = new MarginsCollapseHandler(this, null);
                }
            }
            // Static layout
            for (int i = 0; currentArea != null && i < addedRenderers.Count; i++)
            {
                renderer = addedRenderers[i];
                bool rendererIsFloat = FloatingHelper.IsRendererFloating(renderer);
                bool clearanceOverflowsToNextPage = FloatingHelper.IsClearanceApplied(waitingNextPageRenderers, renderer.GetProperty
                                                                                      <ClearPropertyValue?>(Property.CLEAR));
                if (rendererIsFloat && (floatOverflowedCompletely || clearanceOverflowsToNextPage))
                {
                    waitingNextPageRenderers.Add(renderer);
                    floatOverflowedCompletely = true;
                    continue;
                }
                ProcessWaitingKeepWithNextElement(renderer);
                IList <IRenderer>   resultRenderers  = new List <IRenderer>();
                LayoutResult        result           = null;
                RootLayoutArea      storedArea       = null;
                RootLayoutArea      nextStoredArea   = null;
                MarginsCollapseInfo childMarginsInfo = null;
                if (marginsCollapsingEnabled && currentArea != null && renderer != null)
                {
                    childMarginsInfo = marginsCollapseHandler.StartChildMarginsHandling(renderer, currentArea.GetBBox());
                }
                while (clearanceOverflowsToNextPage || currentArea != null && renderer != null && (result = renderer.SetParent
                                                                                                                (this).Layout(new LayoutContext(currentArea.Clone(), childMarginsInfo, floatRendererAreas))).GetStatus
                           () != LayoutResult.FULL)
                {
                    bool currentAreaNeedsToBeUpdated = false;
                    if (clearanceOverflowsToNextPage)
                    {
                        result = new LayoutResult(LayoutResult.NOTHING, null, null, renderer);
                        currentAreaNeedsToBeUpdated = true;
                    }
                    if (result.GetStatus() == LayoutResult.PARTIAL)
                    {
                        if (rendererIsFloat)
                        {
                            waitingNextPageRenderers.Add(result.GetOverflowRenderer());
                            break;
                        }
                        else
                        {
                            ProcessRenderer(result.GetSplitRenderer(), resultRenderers);
                            if (nextStoredArea != null)
                            {
                                currentArea       = nextStoredArea;
                                currentPageNumber = nextStoredArea.GetPageNumber();
                                nextStoredArea    = null;
                            }
                            else
                            {
                                currentAreaNeedsToBeUpdated = true;
                            }
                        }
                    }
                    else
                    {
                        if (result.GetStatus() == LayoutResult.NOTHING && !clearanceOverflowsToNextPage)
                        {
                            if (result.GetOverflowRenderer() is ImageRenderer)
                            {
                                float imgHeight = ((ImageRenderer)result.GetOverflowRenderer()).GetOccupiedArea().GetBBox().GetHeight();
                                if (!floatRendererAreas.IsEmpty() || currentArea.GetBBox().GetHeight() < imgHeight && !currentArea.IsEmptyArea
                                        ())
                                {
                                    if (rendererIsFloat)
                                    {
                                        waitingNextPageRenderers.Add(result.GetOverflowRenderer());
                                        floatOverflowedCompletely = true;
                                        break;
                                    }
                                    currentAreaNeedsToBeUpdated = true;
                                }
                                else
                                {
                                    ((ImageRenderer)result.GetOverflowRenderer()).AutoScale(currentArea);
                                    result.GetOverflowRenderer().SetProperty(Property.FORCED_PLACEMENT, true);
                                    ILog logger = LogManager.GetLogger(typeof(RootRenderer));
                                    logger.Warn(MessageFormatUtil.Format(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, ""));
                                }
                            }
                            else
                            {
                                if (currentArea.IsEmptyArea() && result.GetAreaBreak() == null)
                                {
                                    if (true.Equals(result.GetOverflowRenderer().GetModelElement().GetProperty <bool?>(Property.KEEP_TOGETHER))
                                        )
                                    {
                                        result.GetOverflowRenderer().GetModelElement().SetProperty(Property.KEEP_TOGETHER, false);
                                        ILog logger = LogManager.GetLogger(typeof(RootRenderer));
                                        logger.Warn(MessageFormatUtil.Format(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, "KeepTogether property will be ignored."
                                                                             ));
                                        if (storedArea != null)
                                        {
                                            nextStoredArea    = currentArea;
                                            currentArea       = storedArea;
                                            currentPageNumber = storedArea.GetPageNumber();
                                        }
                                        storedArea = currentArea;
                                    }
                                    else
                                    {
                                        if (null != result.GetCauseOfNothing() && true.Equals(result.GetCauseOfNothing().GetProperty <bool?>(Property
                                                                                                                                             .KEEP_TOGETHER)))
                                        {
                                            // set KEEP_TOGETHER false on the deepest parent (maybe the element itself) to have KEEP_TOGETHER == true
                                            IRenderer theDeepestKeptTogether = result.GetCauseOfNothing();
                                            IRenderer parent;
                                            while (null == theDeepestKeptTogether.GetModelElement() || null == theDeepestKeptTogether.GetModelElement(
                                                       ).GetOwnProperty <bool?>(Property.KEEP_TOGETHER))
                                            {
                                                parent = ((AbstractRenderer)theDeepestKeptTogether).parent;
                                                if (parent == null)
                                                {
                                                    break;
                                                }
                                                theDeepestKeptTogether = parent;
                                            }
                                            theDeepestKeptTogether.GetModelElement().SetProperty(Property.KEEP_TOGETHER, false);
                                            ILog logger = LogManager.GetLogger(typeof(RootRenderer));
                                            logger.Warn(MessageFormatUtil.Format(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, "KeepTogether property of inner element will be ignored."
                                                                                 ));
                                        }
                                        else
                                        {
                                            if (!true.Equals(renderer.GetProperty <bool?>(Property.FORCED_PLACEMENT)))
                                            {
                                                result.GetOverflowRenderer().SetProperty(Property.FORCED_PLACEMENT, true);
                                                ILog logger = LogManager.GetLogger(typeof(RootRenderer));
                                                logger.Warn(MessageFormatUtil.Format(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, ""));
                                            }
                                            else
                                            {
                                                // FORCED_PLACEMENT was already set to the renderer and
                                                // LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA message was logged.
                                                // This else-clause should never be hit, otherwise there is a bug in FORCED_PLACEMENT implementation.
                                                System.Diagnostics.Debug.Assert(false);
                                                // Still handling this case in order to avoid nasty infinite loops.
                                                break;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    storedArea = currentArea;
                                    if (nextStoredArea != null)
                                    {
                                        currentArea       = nextStoredArea;
                                        currentPageNumber = nextStoredArea.GetPageNumber();
                                        nextStoredArea    = null;
                                    }
                                    else
                                    {
                                        if (rendererIsFloat)
                                        {
                                            waitingNextPageRenderers.Add(result.GetOverflowRenderer());
                                            floatOverflowedCompletely = true;
                                            break;
                                        }
                                        currentAreaNeedsToBeUpdated = true;
                                    }
                                }
                            }
                        }
                    }
                    renderer = result.GetOverflowRenderer();
                    if (marginsCollapsingEnabled)
                    {
                        marginsCollapseHandler.EndChildMarginsHandling(currentArea.GetBBox());
                    }
                    if (currentAreaNeedsToBeUpdated)
                    {
                        UpdateCurrentAndInitialArea(result);
                    }
                    if (marginsCollapsingEnabled)
                    {
                        marginsCollapseHandler = new MarginsCollapseHandler(this, null);
                        childMarginsInfo       = marginsCollapseHandler.StartChildMarginsHandling(renderer, currentArea.GetBBox());
                    }
                    clearanceOverflowsToNextPage = clearanceOverflowsToNextPage && FloatingHelper.IsClearanceApplied(waitingNextPageRenderers
                                                                                                                     , renderer.GetProperty <ClearPropertyValue?>(Property.CLEAR));
                }
                if (marginsCollapsingEnabled)
                {
                    marginsCollapseHandler.EndChildMarginsHandling(currentArea.GetBBox());
                }
                if (null != result && null != result.GetSplitRenderer())
                {
                    renderer = result.GetSplitRenderer();
                }
                // Keep renderer until next element is added for future keep with next adjustments
                if (renderer != null && result != null)
                {
                    if (true.Equals(renderer.GetProperty <bool?>(Property.KEEP_WITH_NEXT)))
                    {
                        if (true.Equals(renderer.GetProperty <bool?>(Property.FORCED_PLACEMENT)))
                        {
                            ILog logger = LogManager.GetLogger(typeof(RootRenderer));
                            logger.Warn(iText.IO.LogMessageConstant.ELEMENT_WAS_FORCE_PLACED_KEEP_WITH_NEXT_WILL_BE_IGNORED);
                            ShrinkCurrentAreaAndProcessRenderer(renderer, resultRenderers, result);
                        }
                        else
                        {
                            keepWithNextHangingRenderer             = renderer;
                            keepWithNextHangingRendererLayoutResult = result;
                        }
                    }
                    else
                    {
                        if (result.GetStatus() != LayoutResult.NOTHING)
                        {
                            ShrinkCurrentAreaAndProcessRenderer(renderer, resultRenderers, result);
                        }
                    }
                }
            }
            for (int i = 0; i < addedPositionedRenderers.Count; i++)
            {
                positionedRenderers.Add(addedPositionedRenderers[i]);
                renderer = positionedRenderers[positionedRenderers.Count - 1];
                int?positionedPageNumber = renderer.GetProperty <int?>(Property.PAGE_NUMBER);
                if (positionedPageNumber == null)
                {
                    positionedPageNumber = currentPageNumber;
                }
                LayoutArea layoutArea;
                // For position=absolute, if none of the top, bottom, left, right properties are provided,
                // the content should be displayed in the flow of the current content, not overlapping it.
                // The behavior is just if it would be statically positioned except it does not affect other elements
                if (Convert.ToInt32(LayoutPosition.ABSOLUTE).Equals(renderer.GetProperty <int?>(Property.POSITION)) && AbstractRenderer
                    .NoAbsolutePositionInfo(renderer))
                {
                    layoutArea = new LayoutArea((int)positionedPageNumber, currentArea.GetBBox().Clone());
                }
                else
                {
                    layoutArea = new LayoutArea((int)positionedPageNumber, initialCurrentArea.GetBBox().Clone());
                }
                Rectangle fullBbox = layoutArea.GetBBox().Clone();
                PreparePositionedRendererAndAreaForLayout(renderer, fullBbox, layoutArea.GetBBox());
                renderer.Layout(new PositionedLayoutContext(new LayoutArea(layoutArea.GetPageNumber(), fullBbox), layoutArea
                                                            ));
                if (immediateFlush)
                {
                    FlushSingleRenderer(renderer);
                    positionedRenderers.JRemoveAt(positionedRenderers.Count - 1);
                }
            }
        }
예제 #2
0
 private void ProcessWaitingKeepWithNextElement(IRenderer renderer)
 {
     if (keepWithNextHangingRenderer != null)
     {
         LayoutArea rest = currentArea.Clone();
         rest.GetBBox().SetHeight(rest.GetBBox().GetHeight() - keepWithNextHangingRendererLayoutResult.GetOccupiedArea
                                      ().GetBBox().GetHeight());
         bool ableToProcessKeepWithNext = false;
         if (renderer.SetParent(this).Layout(new LayoutContext(rest)).GetStatus() != LayoutResult.NOTHING)
         {
             // The area break will not be introduced and we are safe to place everything as is
             ShrinkCurrentAreaAndProcessRenderer(keepWithNextHangingRenderer, new List <IRenderer>(), keepWithNextHangingRendererLayoutResult
                                                 );
             ableToProcessKeepWithNext = true;
         }
         else
         {
             float originalElementHeight = keepWithNextHangingRendererLayoutResult.GetOccupiedArea().GetBBox().GetHeight
                                               ();
             IList <float> trySplitHeightPoints = new List <float>();
             float         delta = 35;
             for (int i = 1; i <= 5 && originalElementHeight - delta * i > originalElementHeight / 2; i++)
             {
                 trySplitHeightPoints.Add(originalElementHeight - delta * i);
             }
             for (int i = 0; i < trySplitHeightPoints.Count && !ableToProcessKeepWithNext; i++)
             {
                 float          curElementSplitHeight       = trySplitHeightPoints[i];
                 RootLayoutArea firstElementSplitLayoutArea = (RootLayoutArea)currentArea.Clone();
                 firstElementSplitLayoutArea.GetBBox().SetHeight(curElementSplitHeight).MoveUp(currentArea.GetBBox().GetHeight
                                                                                                   () - curElementSplitHeight);
                 LayoutResult firstElementSplitLayoutResult = keepWithNextHangingRenderer.SetParent(this).Layout(new LayoutContext
                                                                                                                     (firstElementSplitLayoutArea.Clone()));
                 if (firstElementSplitLayoutResult.GetStatus() == LayoutResult.PARTIAL)
                 {
                     RootLayoutArea storedArea = currentArea;
                     UpdateCurrentAndInitialArea(firstElementSplitLayoutResult);
                     LayoutResult firstElementOverflowLayoutResult = firstElementSplitLayoutResult.GetOverflowRenderer().Layout
                                                                         (new LayoutContext(currentArea.Clone()));
                     if (firstElementOverflowLayoutResult.GetStatus() == LayoutResult.FULL)
                     {
                         LayoutArea secondElementLayoutArea = currentArea.Clone();
                         secondElementLayoutArea.GetBBox().SetHeight(secondElementLayoutArea.GetBBox().GetHeight() - firstElementOverflowLayoutResult
                                                                     .GetOccupiedArea().GetBBox().GetHeight());
                         LayoutResult secondElementLayoutResult = renderer.SetParent(this).Layout(new LayoutContext(secondElementLayoutArea
                                                                                                                    ));
                         if (secondElementLayoutResult.GetStatus() != LayoutResult.NOTHING)
                         {
                             ableToProcessKeepWithNext = true;
                             currentArea       = firstElementSplitLayoutArea;
                             currentPageNumber = firstElementSplitLayoutArea.GetPageNumber();
                             ShrinkCurrentAreaAndProcessRenderer(firstElementSplitLayoutResult.GetSplitRenderer(), new List <IRenderer>(
                                                                     ), firstElementSplitLayoutResult);
                             UpdateCurrentAndInitialArea(firstElementSplitLayoutResult);
                             ShrinkCurrentAreaAndProcessRenderer(firstElementSplitLayoutResult.GetOverflowRenderer(), new List <IRenderer
                                                                                                                                >(), firstElementOverflowLayoutResult);
                         }
                     }
                     if (!ableToProcessKeepWithNext)
                     {
                         currentArea       = storedArea;
                         currentPageNumber = storedArea.GetPageNumber();
                     }
                 }
             }
         }
         if (!ableToProcessKeepWithNext && !currentArea.IsEmptyArea())
         {
             RootLayoutArea storedArea = currentArea;
             UpdateCurrentAndInitialArea(null);
             LayoutResult firstElementLayoutResult = keepWithNextHangingRenderer.SetParent(this).Layout(new LayoutContext
                                                                                                            (currentArea.Clone()));
             if (firstElementLayoutResult.GetStatus() == LayoutResult.FULL)
             {
                 LayoutArea secondElementLayoutArea = currentArea.Clone();
                 secondElementLayoutArea.GetBBox().SetHeight(secondElementLayoutArea.GetBBox().GetHeight() - firstElementLayoutResult
                                                             .GetOccupiedArea().GetBBox().GetHeight());
                 LayoutResult secondElementLayoutResult = renderer.SetParent(this).Layout(new LayoutContext(secondElementLayoutArea
                                                                                                            ));
                 if (secondElementLayoutResult.GetStatus() != LayoutResult.NOTHING)
                 {
                     ableToProcessKeepWithNext = true;
                     ShrinkCurrentAreaAndProcessRenderer(keepWithNextHangingRenderer, new List <IRenderer>(), keepWithNextHangingRendererLayoutResult
                                                         );
                 }
             }
             if (!ableToProcessKeepWithNext)
             {
                 currentArea       = storedArea;
                 currentPageNumber = storedArea.GetPageNumber();
             }
         }
         if (!ableToProcessKeepWithNext)
         {
             ILog logger = LogManager.GetLogger(typeof(RootRenderer));
             logger.Warn(iText.IO.LogMessageConstant.RENDERER_WAS_NOT_ABLE_TO_PROCESS_KEEP_WITH_NEXT);
             ShrinkCurrentAreaAndProcessRenderer(keepWithNextHangingRenderer, new List <IRenderer>(), keepWithNextHangingRendererLayoutResult
                                                 );
         }
         keepWithNextHangingRenderer             = null;
         keepWithNextHangingRendererLayoutResult = null;
     }
 }