protected internal override void FlushSingleRenderer(IRenderer resultRenderer) { Transform transformProp = resultRenderer.GetProperty <Transform>(Property.TRANSFORM); if (!waitingDrawingElements.Contains(resultRenderer)) { ProcessWaitingDrawing(resultRenderer, transformProp, waitingDrawingElements); if (FloatingHelper.IsRendererFloating(resultRenderer) || transformProp != null) { return; } } if (!resultRenderer.IsFlushed() && null != resultRenderer.GetOccupiedArea()) { // TODO Remove checking occupied area to be not null when DEVSIX-1001 is resolved. int pageNum = resultRenderer.GetOccupiedArea().GetPageNumber(); PdfDocument pdfDocument = document.GetPdfDocument(); EnsureDocumentHasNPages(pageNum, null); PdfPage correspondingPage = pdfDocument.GetPage(pageNum); if (correspondingPage.IsFlushed()) { throw new PdfException(PdfException.CannotDrawElementsOnAlreadyFlushedPages); } bool wrapOldContent = pdfDocument.GetReader() != null && pdfDocument.GetWriter() != null && correspondingPage .GetContentStreamCount() > 0 && correspondingPage.GetLastContentStream().GetLength() > 0 && !wrappedContentPage .Contains(pageNum) && pdfDocument.GetNumberOfPages() >= pageNum; wrappedContentPage.Add(pageNum); if (pdfDocument.IsTagged()) { pdfDocument.GetTagStructureContext().GetAutoTaggingPointer().SetPageForTagging(correspondingPage); } resultRenderer.Draw(new DrawContext(pdfDocument, new PdfCanvas(correspondingPage, wrapOldContent), pdfDocument .IsTagged())); } }
private void AlignStaticKids(LineRenderer renderer, float dxRight) { renderer.GetOccupiedArea().GetBBox().MoveRight(dxRight); foreach (IRenderer childRenderer in renderer.GetChildRenderers()) { if (FloatingHelper.IsRendererFloating(childRenderer)) { continue; } childRenderer.Move(dxRight, 0); } }
private void ApplyTextAlignment(TextAlignment?textAlignment, LineLayoutResult result, LineRenderer processedRenderer , Rectangle layoutBox, IList <Rectangle> floatRendererAreas, bool onlyOverflowedFloatsLeft, float lineIndent ) { if (textAlignment == TextAlignment.JUSTIFIED && result.GetStatus() == LayoutResult.PARTIAL && !result.IsSplitForcedByNewline () && !onlyOverflowedFloatsLeft || textAlignment == TextAlignment.JUSTIFIED_ALL) { if (processedRenderer != null) { Rectangle actualLineLayoutBox = layoutBox.Clone(); FloatingHelper.AdjustLineAreaAccordingToFloats(floatRendererAreas, actualLineLayoutBox); processedRenderer.Justify(actualLineLayoutBox.GetWidth() - lineIndent); } } else { if (textAlignment != TextAlignment.LEFT && processedRenderer != null) { Rectangle actualLineLayoutBox = layoutBox.Clone(); FloatingHelper.AdjustLineAreaAccordingToFloats(floatRendererAreas, actualLineLayoutBox); float deltaX = Math.Max(0, actualLineLayoutBox.GetWidth() - lineIndent - processedRenderer.GetOccupiedArea ().GetBBox().GetWidth()); switch (textAlignment) { case TextAlignment.RIGHT: { AlignStaticKids(processedRenderer, deltaX); break; } case TextAlignment.CENTER: { AlignStaticKids(processedRenderer, deltaX / 2); break; } case TextAlignment.JUSTIFIED: { if (BaseDirection.RIGHT_TO_LEFT.Equals(this.GetProperty <BaseDirection?>(Property.BASE_DIRECTION))) { AlignStaticKids(processedRenderer, deltaX); } break; } } } } }
protected internal virtual void ShrinkCurrentAreaAndProcessRenderer(IRenderer renderer, IList <IRenderer> resultRenderers , LayoutResult result) { if (currentArea != null) { float resultRendererHeight = result.GetOccupiedArea().GetBBox().GetHeight(); currentArea.GetBBox().SetHeight(currentArea.GetBBox().GetHeight() - resultRendererHeight); if (currentArea.IsEmptyArea() && (resultRendererHeight > 0 || FloatingHelper.IsRendererFloating(renderer)) ) { currentArea.SetEmptyArea(false); } ProcessRenderer(renderer, resultRenderers); } if (!immediateFlush) { childRenderers.AddAll(resultRenderers); } }
/// <summary><inheritDoc/></summary> protected internal override void FlushSingleRenderer(IRenderer resultRenderer) { Transform transformProp = resultRenderer.GetProperty <Transform>(Property.TRANSFORM); if (!waitingDrawingElements.Contains(resultRenderer)) { ProcessWaitingDrawing(resultRenderer, transformProp, waitingDrawingElements); if (FloatingHelper.IsRendererFloating(resultRenderer) || transformProp != null) { return; } } if (!resultRenderer.IsFlushed()) { bool toTag = canvas.GetPdfDocument().IsTagged() && canvas.IsAutoTaggingEnabled(); TagTreePointer tagPointer = null; if (toTag) { tagPointer = canvas.GetPdfDocument().GetTagStructureContext().GetAutoTaggingPointer(); tagPointer.SetPageForTagging(canvas.GetPage()); bool pageStream = false; for (int i = canvas.GetPage().GetContentStreamCount() - 1; i >= 0; --i) { if (canvas.GetPage().GetContentStream(i).Equals(canvas.GetPdfCanvas().GetContentStream())) { pageStream = true; break; } } if (!pageStream) { tagPointer.SetContentStreamForTagging(canvas.GetPdfCanvas().GetContentStream()); } } resultRenderer.Draw(new DrawContext(canvas.GetPdfDocument(), canvas.GetPdfCanvas(), toTag)); if (toTag) { tagPointer.SetContentStreamForTagging(null); } } }
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); } } }
/// <summary>Defines whether a renderer creates a new "Block formatting context" in terms of CSS.</summary> /// <remarks> /// Defines whether a renderer creates a new "Block formatting context" in terms of CSS. /// <para /> /// See /// <see cref="BlockFormattingContextUtil"/> /// class description for more info. /// </remarks> /// <param name="renderer"> /// an /// <see cref="IRenderer"/> /// to be checked. /// </param> /// <returns>true if given renderer creates a new "Block formatting context" in terms of CSS, false otherwise. /// </returns> public static bool IsRendererCreateBfc(IRenderer renderer) { return((renderer is RootRenderer) || (renderer is CellRenderer) || IsInlineBlock(renderer) || FloatingHelper .IsRendererFloating(renderer) || IsAbsolutePosition(renderer) || IsFixedPosition(renderer) || IsCaption (renderer) || AbstractRenderer.IsOverflowProperty(OverflowPropertyValue.HIDDEN, renderer, Property.OVERFLOW_X ) || AbstractRenderer.IsOverflowProperty(OverflowPropertyValue.HIDDEN, renderer, Property.OVERFLOW_Y)); }
public override LayoutResult Layout(LayoutContext layoutContext) { LayoutArea area = layoutContext.GetArea().Clone(); Rectangle layoutBox = area.GetBBox().Clone(); AffineTransform t = new AffineTransform(); Image modelElement = (Image)(GetModelElement()); PdfXObject xObject = modelElement.GetXObject(); imageWidth = modelElement.GetImageWidth(); imageHeight = modelElement.GetImageHeight(); CalculateImageDimensions(layoutBox, t, xObject); OverflowPropertyValue?overflowX = null != parent?parent.GetProperty <OverflowPropertyValue?>(Property.OVERFLOW_X ) : OverflowPropertyValue.FIT; bool nowrap = false; if (parent is LineRenderer) { nowrap = true.Equals(this.parent.GetOwnProperty <bool?>(Property.NO_SOFT_WRAP_INLINE)); } IList <Rectangle> floatRendererAreas = layoutContext.GetFloatRendererAreas(); float clearHeightCorrection = FloatingHelper.CalculateClearHeightCorrection(this, floatRendererAreas, layoutBox ); FloatPropertyValue?floatPropertyValue = this.GetProperty <FloatPropertyValue?>(Property.FLOAT); if (FloatingHelper.IsRendererFloating(this, floatPropertyValue)) { layoutBox.DecreaseHeight(clearHeightCorrection); FloatingHelper.AdjustFloatedBlockLayoutBox(this, layoutBox, width, floatRendererAreas, floatPropertyValue, overflowX); } else { clearHeightCorrection = FloatingHelper.AdjustLayoutBoxAccordingToFloats(floatRendererAreas, layoutBox, width , clearHeightCorrection, null); } ApplyMargins(layoutBox, false); Border[] borders = GetBorders(); ApplyBorderBox(layoutBox, borders, false); float?declaredMaxHeight = RetrieveMaxHeight(); OverflowPropertyValue?overflowY = null == parent || ((null == declaredMaxHeight || declaredMaxHeight > layoutBox .GetHeight()) && !layoutContext.IsClippedHeight()) ? OverflowPropertyValue.FIT : parent.GetProperty <OverflowPropertyValue? >(Property.OVERFLOW_Y); bool processOverflowX = !IsOverflowFit(overflowX) || nowrap; bool processOverflowY = !IsOverflowFit(overflowY); if (IsAbsolutePosition()) { ApplyAbsolutePosition(layoutBox); } occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox .GetHeight(), 0, 0)); float imageItselfScaledWidth = (float)width; float imageItselfScaledHeight = (float)height; if (IsFixedLayout()) { fixedXPosition = this.GetPropertyAsFloat(Property.LEFT); fixedYPosition = this.GetPropertyAsFloat(Property.BOTTOM); } float?angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); // See in adjustPositionAfterRotation why angle = 0 is necessary if (null == angle) { angle = 0f; } t.Rotate((float)angle); initialOccupiedAreaBBox = GetOccupiedAreaBBox().Clone(); float scaleCoef = AdjustPositionAfterRotation((float)angle, layoutBox.GetWidth(), layoutBox.GetHeight()); imageItselfScaledHeight *= scaleCoef; imageItselfScaledWidth *= scaleCoef; initialOccupiedAreaBBox.MoveDown(imageItselfScaledHeight); initialOccupiedAreaBBox.SetHeight(imageItselfScaledHeight); initialOccupiedAreaBBox.SetWidth(imageItselfScaledWidth); if (xObject is PdfFormXObject) { t.Scale(scaleCoef, scaleCoef); } GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); // indicates whether the placement is forced bool isPlacingForced = false; if (width > layoutBox.GetWidth() || height > layoutBox.GetHeight()) { if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) || (width > layoutBox.GetWidth() && processOverflowX ) || (height > layoutBox.GetHeight() && processOverflowY)) { isPlacingForced = true; } else { ApplyMargins(initialOccupiedAreaBBox, true); ApplyBorderBox(initialOccupiedAreaBBox, true); occupiedArea.GetBBox().SetHeight(initialOccupiedAreaBBox.GetHeight()); return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this)); } } occupiedArea.GetBBox().MoveDown((float)height); if (borders[3] != null) { height += (float)Math.Sin((float)angle) * borders[3].GetWidth(); } occupiedArea.GetBBox().SetHeight((float)height); occupiedArea.GetBBox().SetWidth((float)width); UnitValue leftMargin = this.GetPropertyAsUnitValue(Property.MARGIN_LEFT); if (!leftMargin.IsPointValue()) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ImageRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property .MARGIN_LEFT)); } UnitValue topMargin = this.GetPropertyAsUnitValue(Property.MARGIN_TOP); if (!topMargin.IsPointValue()) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ImageRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property .MARGIN_TOP)); } if (0 != leftMargin.GetValue() || 0 != topMargin.GetValue()) { TranslateImage(leftMargin.GetValue(), topMargin.GetValue(), t); GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); } ApplyBorderBox(occupiedArea.GetBBox(), borders, true); ApplyMargins(occupiedArea.GetBBox(), true); if (angle != 0) { ApplyRotationLayout((float)angle); } float unscaledWidth = occupiedArea.GetBBox().GetWidth() / scaleCoef; MinMaxWidth minMaxWidth = new MinMaxWidth(unscaledWidth, unscaledWidth, 0); UnitValue rendererWidth = this.GetProperty <UnitValue>(Property.WIDTH); if (rendererWidth != null && rendererWidth.IsPercentValue()) { minMaxWidth.SetChildrenMinWidth(0); float coeff = imageWidth / (float)RetrieveWidth(area.GetBBox().GetWidth()); minMaxWidth.SetChildrenMaxWidth(unscaledWidth * coeff); } else { bool autoScale = HasProperty(Property.AUTO_SCALE) && (bool)this.GetProperty <bool?>(Property.AUTO_SCALE); bool autoScaleWidth = HasProperty(Property.AUTO_SCALE_WIDTH) && (bool)this.GetProperty <bool?>(Property.AUTO_SCALE_WIDTH ); if (autoScale || autoScaleWidth) { minMaxWidth.SetChildrenMinWidth(0); } } FloatingHelper.RemoveFloatsAboveRendererBottom(floatRendererAreas, this); LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, floatRendererAreas, layoutContext.GetArea().GetBBox(), clearHeightCorrection, false); ApplyAbsolutePositionIfNeeded(layoutContext); return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea, null, null, isPlacingForced ? this : null ).SetMinMaxWidth(minMaxWidth)); }
protected internal virtual LayoutResult DirectLayout(LayoutContext layoutContext) { bool wasHeightClipped = false; bool wasParentsHeightClipped = layoutContext.IsClippedHeight(); int pageNumber = layoutContext.GetArea().GetPageNumber(); bool anythingPlaced = false; bool firstLineInBox = true; LineRenderer currentRenderer = (LineRenderer) new LineRenderer().SetParent(this); Rectangle parentBBox = layoutContext.GetArea().GetBBox().Clone(); MarginsCollapseHandler marginsCollapseHandler = null; bool marginsCollapsingEnabled = true.Equals(GetPropertyAsBoolean(Property.COLLAPSING_MARGINS)); if (marginsCollapsingEnabled) { marginsCollapseHandler = new MarginsCollapseHandler(this, layoutContext.GetMarginsCollapseInfo()); } OverflowPropertyValue?overflowX = this.GetProperty <OverflowPropertyValue?>(Property.OVERFLOW_X); bool?nowrapProp = this.GetPropertyAsBoolean(Property.NO_SOFT_WRAP_INLINE); currentRenderer.SetProperty(Property.NO_SOFT_WRAP_INLINE, nowrapProp); bool notAllKidsAreFloats = false; IList <Rectangle> floatRendererAreas = layoutContext.GetFloatRendererAreas(); FloatPropertyValue?floatPropertyValue = this.GetProperty <FloatPropertyValue?>(Property.FLOAT); float clearHeightCorrection = FloatingHelper.CalculateClearHeightCorrection(this, floatRendererAreas, parentBBox ); FloatingHelper.ApplyClearance(parentBBox, marginsCollapseHandler, clearHeightCorrection, FloatingHelper.IsRendererFloating (this)); float?blockWidth = RetrieveWidth(parentBBox.GetWidth()); if (FloatingHelper.IsRendererFloating(this, floatPropertyValue)) { blockWidth = FloatingHelper.AdjustFloatedBlockLayoutBox(this, parentBBox, blockWidth, floatRendererAreas, floatPropertyValue, overflowX); floatRendererAreas = new List <Rectangle>(); } if (0 == childRenderers.Count) { anythingPlaced = true; currentRenderer = null; } bool isPositioned = IsPositioned(); float?rotation = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); float?blockMaxHeight = RetrieveMaxHeight(); OverflowPropertyValue?overflowY = (null == blockMaxHeight || blockMaxHeight > parentBBox.GetHeight()) && !wasParentsHeightClipped ? OverflowPropertyValue.FIT : this.GetProperty <OverflowPropertyValue?>(Property .OVERFLOW_Y); if (rotation != null || IsFixedLayout()) { parentBBox.MoveDown(AbstractRenderer.INF - parentBBox.GetHeight()).SetHeight(AbstractRenderer.INF); } if (rotation != null && !FloatingHelper.IsRendererFloating(this)) { blockWidth = RotationUtils.RetrieveRotatedLayoutWidth(parentBBox.GetWidth(), this); } if (marginsCollapsingEnabled) { marginsCollapseHandler.StartMarginsCollapse(parentBBox); } Border[] borders = GetBorders(); UnitValue[] paddings = GetPaddings(); float additionalWidth = ApplyBordersPaddingsMargins(parentBBox, borders, paddings); ApplyWidth(parentBBox, blockWidth, overflowX); wasHeightClipped = ApplyMaxHeight(parentBBox, blockMaxHeight, marginsCollapseHandler, false, wasParentsHeightClipped , overflowY); MinMaxWidth minMaxWidth = new MinMaxWidth(additionalWidth); AbstractWidthHandler widthHandler = new MaxMaxWidthHandler(minMaxWidth); IList <Rectangle> areas; if (isPositioned) { areas = JavaCollectionsUtil.SingletonList(parentBBox); } else { areas = InitElementAreas(new LayoutArea(pageNumber, parentBBox)); } occupiedArea = new LayoutArea(pageNumber, new Rectangle(parentBBox.GetX(), parentBBox.GetY() + parentBBox. GetHeight(), parentBBox.GetWidth(), 0)); ShrinkOccupiedAreaForAbsolutePosition(); int currentAreaPos = 0; Rectangle layoutBox = areas[0].Clone(); lines = new List <LineRenderer>(); foreach (IRenderer child in childRenderers) { notAllKidsAreFloats = notAllKidsAreFloats || !FloatingHelper.IsRendererFloating(child); currentRenderer.AddChild(child); } float lastYLine = layoutBox.GetY() + layoutBox.GetHeight(); float previousDescent = 0; float lastLineBottomLeadingIndent = 0; bool onlyOverflowedFloatsLeft = false; IList <IRenderer> inlineFloatsOverflowedToNextPage = new List <IRenderer>(); bool floatOverflowedToNextPageWithNothing = false; // rectangles are compared by instances ICollection <Rectangle> nonChildFloatingRendererAreas = new HashSet <Rectangle>(floatRendererAreas); if (marginsCollapsingEnabled && childRenderers.Count > 0) { // passing null is sufficient to notify that there is a kid, however we don't care about it and it's margins marginsCollapseHandler.StartChildMarginsHandling(null, layoutBox); } bool includeFloatsInOccupiedArea = BlockFormattingContextUtil.IsRendererCreateBfc(this); while (currentRenderer != null) { currentRenderer.SetProperty(Property.TAB_DEFAULT, this.GetPropertyAsFloat(Property.TAB_DEFAULT)); currentRenderer.SetProperty(Property.TAB_STOPS, this.GetProperty <Object>(Property.TAB_STOPS)); float lineIndent = anythingPlaced ? 0 : (float)this.GetPropertyAsFloat(Property.FIRST_LINE_INDENT); Rectangle childLayoutBox = new Rectangle(layoutBox.GetX(), layoutBox.GetY(), layoutBox.GetWidth(), layoutBox .GetHeight()); currentRenderer.SetProperty(Property.OVERFLOW_X, overflowX); currentRenderer.SetProperty(Property.OVERFLOW_Y, overflowY); LineLayoutContext lineLayoutContext = new LineLayoutContext(new LayoutArea(pageNumber, childLayoutBox), null , floatRendererAreas, wasHeightClipped || wasParentsHeightClipped).SetTextIndent(lineIndent).SetFloatOverflowedToNextPageWithNothing (floatOverflowedToNextPageWithNothing); LineLayoutResult result = (LineLayoutResult)((LineRenderer)currentRenderer.SetParent(this)).Layout(lineLayoutContext ); if (result.GetStatus() == LayoutResult.NOTHING) { float?lineShiftUnderFloats = FloatingHelper.CalculateLineShiftUnderFloats(floatRendererAreas, layoutBox); if (lineShiftUnderFloats != null) { layoutBox.DecreaseHeight((float)lineShiftUnderFloats); firstLineInBox = true; continue; } bool allRemainingKidsAreFloats = !currentRenderer.childRenderers.IsEmpty(); foreach (IRenderer renderer in currentRenderer.childRenderers) { allRemainingKidsAreFloats = allRemainingKidsAreFloats && FloatingHelper.IsRendererFloating(renderer); } if (allRemainingKidsAreFloats) { onlyOverflowedFloatsLeft = true; } } floatOverflowedToNextPageWithNothing = lineLayoutContext.IsFloatOverflowedToNextPageWithNothing(); if (result.GetFloatsOverflowedToNextPage() != null) { inlineFloatsOverflowedToNextPage.AddAll(result.GetFloatsOverflowedToNextPage()); } float minChildWidth = 0; float maxChildWidth = 0; if (result is MinMaxWidthLayoutResult) { minChildWidth = ((MinMaxWidthLayoutResult)result).GetMinMaxWidth().GetMinWidth(); maxChildWidth = ((MinMaxWidthLayoutResult)result).GetMinMaxWidth().GetMaxWidth(); } widthHandler.UpdateMinChildWidth(minChildWidth); widthHandler.UpdateMaxChildWidth(maxChildWidth); LineRenderer processedRenderer = null; if (result.GetStatus() == LayoutResult.FULL) { processedRenderer = currentRenderer; } else { if (result.GetStatus() == LayoutResult.PARTIAL) { processedRenderer = (LineRenderer)result.GetSplitRenderer(); } } if (onlyOverflowedFloatsLeft) { // This is done to trick ParagraphRenderer to break rendering and to overflow to the next page. // The `onlyOverflowedFloatsLeft` is set to true only when no other content is left except // overflowed floating elements. processedRenderer = null; } TextAlignment?textAlignment = (TextAlignment?)this.GetProperty <TextAlignment?>(Property.TEXT_ALIGNMENT, TextAlignment .LEFT); ApplyTextAlignment(textAlignment, result, processedRenderer, layoutBox, floatRendererAreas, onlyOverflowedFloatsLeft , lineIndent); Leading leading = RenderingMode.HTML_MODE.Equals(this.GetProperty <RenderingMode?>(Property.RENDERING_MODE) ) ? null : this.GetProperty <Leading>(Property.LEADING); // could be false if e.g. line contains only floats bool lineHasContent = processedRenderer != null && processedRenderer.GetOccupiedArea().GetBBox().GetHeight () > 0; bool isFit = processedRenderer != null; float deltaY = 0; if (isFit && !RenderingMode.HTML_MODE.Equals(this.GetProperty <RenderingMode?>(Property.RENDERING_MODE))) { if (lineHasContent) { float indentFromLastLine = previousDescent - lastLineBottomLeadingIndent - (leading != null ? processedRenderer .GetTopLeadingIndent(leading) : 0) - processedRenderer.GetMaxAscent(); // TODO this is a workaround. To be refactored if (processedRenderer != null && processedRenderer.ContainsImage()) { indentFromLastLine += previousDescent; } deltaY = lastYLine + indentFromLastLine - processedRenderer.GetYLine(); lastLineBottomLeadingIndent = leading != null?processedRenderer.GetBottomLeadingIndent(leading) : 0; // TODO this is a workaround. To be refactored if (lastLineBottomLeadingIndent < 0 && processedRenderer.ContainsImage()) { lastLineBottomLeadingIndent = 0; } } // for the first and last line in a paragraph, leading is smaller if (firstLineInBox) { deltaY = processedRenderer != null && leading != null ? -processedRenderer.GetTopLeadingIndent(leading) : 0; } isFit = leading == null || processedRenderer.GetOccupiedArea().GetBBox().GetY() + deltaY >= layoutBox.GetY (); } if (!isFit && (null == processedRenderer || IsOverflowFit(overflowY))) { if (currentAreaPos + 1 < areas.Count) { layoutBox = areas[++currentAreaPos].Clone(); lastYLine = layoutBox.GetY() + layoutBox.GetHeight(); firstLineInBox = true; } else { bool keepTogether = IsKeepTogether(); if (keepTogether) { floatRendererAreas.RetainAll(nonChildFloatingRendererAreas); return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, null, null, this, null == result.GetCauseOfNothing () ? this : result.GetCauseOfNothing())); } else { if (marginsCollapsingEnabled) { if (anythingPlaced && notAllKidsAreFloats) { marginsCollapseHandler.EndChildMarginsHandling(layoutBox); } } // On page split, if not only overflowed floats left, content will be drawn on next page, i.e. under all floats on this page bool includeFloatsInOccupiedAreaOnSplit = !onlyOverflowedFloatsLeft || includeFloatsInOccupiedArea; if (includeFloatsInOccupiedAreaOnSplit) { FloatingHelper.IncludeChildFloatsInOccupiedArea(floatRendererAreas, this, nonChildFloatingRendererAreas); FixOccupiedAreaIfOverflowedX(overflowX, layoutBox); } if (marginsCollapsingEnabled) { marginsCollapseHandler.EndMarginsCollapse(layoutBox); } bool minHeightOverflowed = false; if (!includeFloatsInOccupiedAreaOnSplit) { AbstractRenderer minHeightOverflow = ApplyMinHeight(overflowY, layoutBox); minHeightOverflowed = minHeightOverflow != null; ApplyVerticalAlignment(); } iText.Layout.Renderer.ParagraphRenderer[] split = Split(); split[0].lines = lines; foreach (LineRenderer line in lines) { split[0].childRenderers.AddAll(line.GetChildRenderers()); } split[1].childRenderers.AddAll(inlineFloatsOverflowedToNextPage); if (processedRenderer != null) { split[1].childRenderers.AddAll(processedRenderer.GetChildRenderers()); } if (result.GetOverflowRenderer() != null) { split[1].childRenderers.AddAll(result.GetOverflowRenderer().GetChildRenderers()); } if (onlyOverflowedFloatsLeft && !includeFloatsInOccupiedArea && !minHeightOverflowed) { FloatingHelper.RemoveParentArtifactsOnPageSplitIfOnlyFloatsOverflow(split[1]); } float usedHeight = occupiedArea.GetBBox().GetHeight(); if (!includeFloatsInOccupiedAreaOnSplit) { Rectangle commonRectangle = Rectangle.GetCommonRectangle(layoutBox, occupiedArea.GetBBox()); usedHeight = commonRectangle.GetHeight(); } UpdateHeightsOnSplit(usedHeight, wasHeightClipped, this, split[1], includeFloatsInOccupiedAreaOnSplit); CorrectFixedLayout(layoutBox); ApplyPaddings(occupiedArea.GetBBox(), paddings, true); ApplyBorderBox(occupiedArea.GetBBox(), borders, true); ApplyMargins(occupiedArea.GetBBox(), true); ApplyAbsolutePositionIfNeeded(layoutContext); LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, layoutContext.GetFloatRendererAreas (), layoutContext.GetArea().GetBBox(), clearHeightCorrection, marginsCollapsingEnabled); if (wasHeightClipped) { return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea, split[0], null).SetMinMaxWidth(minMaxWidth )); } else { if (anythingPlaced) { return(new MinMaxWidthLayoutResult(LayoutResult.PARTIAL, editedArea, split[0], split[1]).SetMinMaxWidth(minMaxWidth )); } else { if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), currentRenderer.GetOccupiedArea( ).GetBBox())); FixOccupiedAreaIfOverflowedX(overflowX, layoutBox); parent.SetProperty(Property.FULL, true); lines.Add(currentRenderer); // Force placement of children we have and do not force placement of the others if (LayoutResult.PARTIAL == result.GetStatus()) { IRenderer childNotRendered = result.GetCauseOfNothing(); int firstNotRendered = currentRenderer.childRenderers.IndexOf(childNotRendered); currentRenderer.childRenderers.RetainAll(currentRenderer.childRenderers.SubList(0, firstNotRendered)); split[1].childRenderers.RemoveAll(split[1].childRenderers.SubList(0, firstNotRendered)); return(new MinMaxWidthLayoutResult(LayoutResult.PARTIAL, editedArea, this, split[1], null).SetMinMaxWidth( minMaxWidth)); } else { return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea, null, null, this).SetMinMaxWidth(minMaxWidth )); } } else { floatRendererAreas.RetainAll(nonChildFloatingRendererAreas); return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, null, null, this, null == result.GetCauseOfNothing () ? this : result.GetCauseOfNothing())); } } } } } } else { if (leading != null) { processedRenderer.ApplyLeading(deltaY); if (lineHasContent) { lastYLine = processedRenderer.GetYLine(); } } if (lineHasContent) { occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), processedRenderer.GetOccupiedArea ().GetBBox())); FixOccupiedAreaIfOverflowedX(overflowX, layoutBox); } firstLineInBox = false; layoutBox.SetHeight(processedRenderer.GetOccupiedArea().GetBBox().GetY() - layoutBox.GetY()); lines.Add(processedRenderer); anythingPlaced = true; currentRenderer = (LineRenderer)result.GetOverflowRenderer(); previousDescent = processedRenderer.GetMaxDescent(); if (!inlineFloatsOverflowedToNextPage.IsEmpty() && result.GetOverflowRenderer() == null) { onlyOverflowedFloatsLeft = true; // dummy renderer to trick paragraph renderer to continue kids loop currentRenderer = new LineRenderer(); } } } if (!RenderingMode.HTML_MODE.Equals(this.GetProperty <RenderingMode?>(Property.RENDERING_MODE))) { float moveDown = lastLineBottomLeadingIndent; if (IsOverflowFit(overflowY) && moveDown > occupiedArea.GetBBox().GetY() - layoutBox.GetY()) { moveDown = occupiedArea.GetBBox().GetY() - layoutBox.GetY(); } occupiedArea.GetBBox().MoveDown(moveDown); occupiedArea.GetBBox().SetHeight(occupiedArea.GetBBox().GetHeight() + moveDown); } if (marginsCollapsingEnabled) { if (childRenderers.Count > 0 && notAllKidsAreFloats) { marginsCollapseHandler.EndChildMarginsHandling(layoutBox); } } if (includeFloatsInOccupiedArea) { FloatingHelper.IncludeChildFloatsInOccupiedArea(floatRendererAreas, this, nonChildFloatingRendererAreas); FixOccupiedAreaIfOverflowedX(overflowX, layoutBox); } if (wasHeightClipped) { FixOccupiedAreaIfOverflowedY(overflowY, layoutBox); } if (marginsCollapsingEnabled) { marginsCollapseHandler.EndMarginsCollapse(layoutBox); } AbstractRenderer overflowRenderer = ApplyMinHeight(overflowY, layoutBox); if (overflowRenderer != null && IsKeepTogether()) { floatRendererAreas.RetainAll(nonChildFloatingRendererAreas); return(new LayoutResult(LayoutResult.NOTHING, null, null, this, this)); } CorrectFixedLayout(layoutBox); ApplyPaddings(occupiedArea.GetBBox(), paddings, true); ApplyBorderBox(occupiedArea.GetBBox(), borders, true); ApplyMargins(occupiedArea.GetBBox(), true); ApplyAbsolutePositionIfNeeded(layoutContext); if (rotation != null) { ApplyRotationLayout(layoutContext.GetArea().GetBBox().Clone()); if (IsNotFittingLayoutArea(layoutContext.GetArea())) { if (IsNotFittingWidth(layoutContext.GetArea()) && !IsNotFittingHeight(layoutContext.GetArea())) { LogManager.GetLogger(GetType()).Warn(MessageFormatUtil.Format(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA , "It fits by height so it will be forced placed")); } else { if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { floatRendererAreas.RetainAll(nonChildFloatingRendererAreas); return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, null, null, this, this)); } } } } ApplyVerticalAlignment(); FloatingHelper.RemoveFloatsAboveRendererBottom(floatRendererAreas, this); LayoutArea editedArea_1 = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, layoutContext.GetFloatRendererAreas (), layoutContext.GetArea().GetBBox(), clearHeightCorrection, marginsCollapsingEnabled); if (null == overflowRenderer) { return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea_1, null, null, null).SetMinMaxWidth(minMaxWidth )); } else { return(new MinMaxWidthLayoutResult(LayoutResult.PARTIAL, editedArea_1, this, overflowRenderer, null).SetMinMaxWidth (minMaxWidth)); } }