diff --git a/itext/itext.layout/itext/layout/renderer/FlexContainerRenderer.cs b/itext/itext.layout/itext/layout/renderer/FlexContainerRenderer.cs index 6a82f8390..72ca21b93 100644 --- a/itext/itext.layout/itext/layout/renderer/FlexContainerRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/FlexContainerRenderer.cs @@ -33,8 +33,10 @@ You should have received a copy of the GNU Affero General Public License using iText.Layout.Minmaxwidth; using iText.Layout.Properties; -namespace iText.Layout.Renderer { - public class FlexContainerRenderer : DivRenderer { +namespace iText.Layout.Renderer +{ + public class FlexContainerRenderer : DivRenderer + { /// /// Used for caching purposes in FlexUtil /// We couldn't find the real use case when this map contains more than 1 entry @@ -48,7 +50,7 @@ public class FlexContainerRenderer : DivRenderer { private IFlexItemMainDirector flexItemMainDirector = null; /// Child renderers and their heights and min heights before the layout. - private readonly IDictionary> heights = new Dictionary> heights = new Dictionary>(); /// Creates a FlexContainerRenderer from its corresponding layout object. @@ -58,7 +60,8 @@ public class FlexContainerRenderer : DivRenderer { /// which this object should manage /// public FlexContainerRenderer(Div modelElement) - : base(modelElement) { + : base(modelElement) + { } /// @@ -79,32 +82,54 @@ public FlexContainerRenderer(Div modelElement) /// renderer will be created. /// /// new renderer instance - public override IRenderer GetNextRenderer() { + public override IRenderer GetNextRenderer() + { LogWarningIfGetNextRendererNotOverridden(typeof(iText.Layout.Renderer.FlexContainerRenderer), this.GetType ()); return new iText.Layout.Renderer.FlexContainerRenderer((Div)modelElement); } /// - public override LayoutResult Layout(LayoutContext layoutContext) { + public override LayoutResult Layout(LayoutContext layoutContext) + { Rectangle layoutContextRectangle = layoutContext.GetArea().GetBBox(); SetThisAsParent(GetChildRenderers()); lines = FlexUtil.CalculateChildrenRectangles(layoutContextRectangle, this); ApplyWrapReverse(); + for (int j = 0; j < lines.Count; j++) + { + for (int i = 0; i < lines[j].Count; i++) + { + if (lines[j][i].GetRenderer() is DivRenderer divRenderer && + divRenderer.GetModelElement() is Div div && + div.HasProperty(Property.AREA_BREAK_TYPE) && + div.GetProperty(Property.AREA_BREAK_TYPE) == AreaBreakType.NEXT_PAGE) + { + lines[j][i] = new FlexItemInfo( + new AreaBreakRenderer(new AreaBreak(AreaBreakType.NEXT_PAGE)), + new Rectangle(0, 0) + ); + } + } + } IList renderers = GetFlexItemMainDirector().ApplyDirection(lines); RemoveAllChildRenderers(GetChildRenderers()); AddAllChildRenderers(renderers); IList renderersToOverflow = RetrieveRenderersToOverflow(layoutContextRectangle); IList previousWidths = new List(); - foreach (IList line in lines) { - foreach (FlexItemInfo itemInfo in line) { + foreach (IList line in lines) + { + foreach (FlexItemInfo itemInfo in line.Where(x => x is AbstractRenderer)) + { Rectangle rectangleWithoutBordersMarginsPaddings; - if (AbstractRenderer.IsBorderBoxSizing(itemInfo.GetRenderer())) { - rectangleWithoutBordersMarginsPaddings = itemInfo.GetRenderer().ApplyMargins(itemInfo.GetRectangle().Clone + if (AbstractRenderer.IsBorderBoxSizing(itemInfo.GetRenderer())) + { + rectangleWithoutBordersMarginsPaddings = ((AbstractRenderer)itemInfo.GetRenderer()).ApplyMargins(itemInfo.GetRectangle().Clone (), false); } - else { - rectangleWithoutBordersMarginsPaddings = itemInfo.GetRenderer().ApplyMarginsBordersPaddings(itemInfo.GetRectangle + else + { + rectangleWithoutBordersMarginsPaddings = ((AbstractRenderer)itemInfo.GetRenderer()).ApplyMarginsBordersPaddings(itemInfo.GetRectangle ().Clone(), false); } heights.Put(itemInfo.GetRenderer(), new Tuple2(itemInfo.GetRenderer().GetProperty line in lines) { - foreach (FlexItemInfo itemInfo in line) { + foreach (IList line in lines) + { + foreach (FlexItemInfo itemInfo in line.Where(x => x is AbstractRenderer)) + { itemInfo.GetRenderer().SetProperty(Property.WIDTH, previousWidths[counter]); Tuple2 curHeights = heights.Get(itemInfo.GetRenderer()); itemInfo.GetRenderer().SetProperty(Property.HEIGHT, curHeights.GetFirst()); @@ -145,44 +173,54 @@ public override LayoutResult Layout(LayoutContext layoutContext) { } /// - public override MinMaxWidth GetMinMaxWidth() { + public override MinMaxWidth GetMinMaxWidth() + { MinMaxWidth minMaxWidth = new MinMaxWidth(CalculateAdditionalWidth(this)); AbstractWidthHandler minMaxWidthHandler = new MaxMaxWidthHandler(minMaxWidth); - if (!SetMinMaxWidthBasedOnFixedWidth(minMaxWidth)) { + if (!SetMinMaxWidthBasedOnFixedWidth(minMaxWidth)) + { float? minWidth = HasAbsoluteUnitValue(Property.MIN_WIDTH) ? RetrieveMinWidth(0) : null; float? maxWidth = HasAbsoluteUnitValue(Property.MAX_WIDTH) ? RetrieveMaxWidth(0) : null; - if (minWidth == null || maxWidth == null) { + if (minWidth == null || maxWidth == null) + { FindMinMaxWidthIfCorrespondingPropertiesAreNotSet(minMaxWidth, minMaxWidthHandler); } - if (minWidth != null) { + if (minWidth != null) + { minMaxWidth.SetChildrenMinWidth((float)minWidth); } // if max-width was defined explicitly, it shouldn't be overwritten - if (maxWidth == null) { - if (minMaxWidth.GetChildrenMinWidth() > minMaxWidth.GetChildrenMaxWidth()) { + if (maxWidth == null) + { + if (minMaxWidth.GetChildrenMinWidth() > minMaxWidth.GetChildrenMaxWidth()) + { minMaxWidth.SetChildrenMaxWidth(minMaxWidth.GetChildrenMinWidth()); } } - else { + else + { minMaxWidth.SetChildrenMaxWidth((float)maxWidth); } } - if (this.GetPropertyAsFloat(Property.ROTATION_ANGLE) != null) { + if (this.GetPropertyAsFloat(Property.ROTATION_ANGLE) != null) + { return RotationUtils.CountRotationMinMaxWidth(minMaxWidth, this); } return minMaxWidth; } -//\cond DO_NOT_DOCUMENT - internal virtual IFlexItemMainDirector GetFlexItemMainDirector() { - if (flexItemMainDirector == null) { + //\cond DO_NOT_DOCUMENT + internal virtual IFlexItemMainDirector GetFlexItemMainDirector() + { + if (flexItemMainDirector == null) + { flexItemMainDirector = CreateMainDirector(); } return flexItemMainDirector; } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT /// Check if flex container is wrapped reversely. /// /// @@ -191,29 +229,33 @@ internal virtual IFlexItemMainDirector GetFlexItemMainDirector() { /// /// otherwise. /// - internal virtual bool IsWrapReverse() { - return FlexWrapPropertyValue.WRAP_REVERSE == this.GetProperty(Property.FLEX_WRAP, + internal virtual bool IsWrapReverse() + { + return FlexWrapPropertyValue.WRAP_REVERSE == this.GetProperty(Property.FLEX_WRAP, null); } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT /// internal override AbstractRenderer[] CreateSplitAndOverflowRenderers(int childPos, int layoutStatus, LayoutResult childResult, IDictionary waitingFloatsSplitRenderers, IList waitingOverflowFloatRenderers - ) { + ) + { AbstractRenderer splitRenderer = CreateSplitRenderer(layoutStatus); AbstractRenderer overflowRenderer = CreateOverflowRenderer(layoutStatus); IRenderer childRenderer = GetChildRenderers()[childPos]; bool forcedPlacement = true.Equals(this.GetProperty(Property.FORCED_PLACEMENT)); bool metChildRenderer = false; - for (int i = 0; i < lines.Count; ++i) { + for (int i = 0; i < lines.Count; ++i) + { IList line = lines[i]; bool isSplitLine = line.Any((flexItem) => flexItem.GetRenderer() == childRenderer); metChildRenderer = metChildRenderer || isSplitLine; // If the renderer to split is in the current line if (isSplitLine && !forcedPlacement && layoutStatus == LayoutResult.PARTIAL && (!FlexUtil.IsColumnDirection - (this) || (i == 0 && line[0].GetRenderer() == childRenderer))) { + (this) || (i == 0 && line[0].GetRenderer() == childRenderer))) + { // It has sense to call it also for LayoutResult.NOTHING. And then try to layout remaining renderers // in line inside fillSplitOverflowRenderersForPartialResult to see if some of them can be left or // partially left on the first page (in split renderer). But it's not that easy. @@ -223,26 +265,39 @@ internal override AbstractRenderer[] CreateSplitAndOverflowRenderers(int childPo ); GetFlexItemMainDirector().ApplyDirectionForLine(overflowRenderer.GetChildRenderers()); } - else { + else + { IList overflowRendererChildren = new List(); bool isSingleColumn = lines.Count == 1 && FlexUtil.IsColumnDirection(this); bool metChildRendererInLine = false; - foreach (FlexItemInfo itemInfo in line) { + foreach (FlexItemInfo itemInfo in line) + { metChildRendererInLine = metChildRendererInLine || itemInfo.GetRenderer() == childRenderer; - if ((!isSingleColumn && metChildRenderer || metChildRendererInLine) && !forcedPlacement) { - overflowRendererChildren.Add(itemInfo.GetRenderer()); + if (itemInfo.GetRenderer() == childRenderer && childRenderer is AreaBreakRenderer) + { + continue; } - else { - splitRenderer.AddChildRenderer(itemInfo.GetRenderer()); + else + { + if ((!isSingleColumn && metChildRenderer || metChildRendererInLine) && !forcedPlacement) + { + overflowRendererChildren.Add(itemInfo.GetRenderer()); + } + else + { + splitRenderer.AddChildRenderer(itemInfo.GetRenderer()); + } } } GetFlexItemMainDirector().ApplyDirectionForLine(overflowRendererChildren); // If wrapped reversely we should add a line into beginning to correctly recalculate // and inverse lines while layouting overflowRenderer. - if (IsWrapReverse()) { + if (IsWrapReverse()) + { overflowRenderer.AddAllChildRenderers(0, overflowRendererChildren); } - else { + else + { overflowRenderer.AddAllChildRenderers(overflowRendererChildren); } } @@ -250,19 +305,22 @@ internal override AbstractRenderer[] CreateSplitAndOverflowRenderers(int childPo overflowRenderer.DeleteOwnProperty(Property.FORCED_PLACEMENT); return new AbstractRenderer[] { splitRenderer, overflowRenderer }; } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal override LayoutResult ProcessNotFullChildResult(LayoutContext layoutContext, IDictionary waitingFloatsSplitRenderers, IList waitingOverflowFloatRenderers, bool wasHeightClipped, + > waitingFloatsSplitRenderers, IList waitingOverflowFloatRenderers, bool wasHeightClipped, IList floatRendererAreas, bool marginsCollapsingEnabled, float clearHeightCorrection, Border [] borders, UnitValue[] paddings, IList areas, int currentAreaPos, Rectangle layoutBox, ICollection nonChildFloatingRendererAreas, IRenderer causeOfNothing, bool anythingPlaced, int childPos - , LayoutResult result) { + , LayoutResult result) + { bool keepTogether = IsKeepTogether(causeOfNothing); - if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) || wasHeightClipped) { + if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) || wasHeightClipped) + { AbstractRenderer splitRenderer = keepTogether ? null : CreateSplitRenderer(result.GetStatus()); - if (splitRenderer != null) { + if (splitRenderer != null) + { splitRenderer.SetChildRenderers(GetChildRenderers()); } return new LayoutResult(LayoutResult.FULL, GetOccupiedAreaInCaseNothingWasWrappedWithFull(result, splitRenderer @@ -274,10 +332,12 @@ internal override LayoutResult ProcessNotFullChildResult(LayoutContext layoutCon AbstractRenderer overflowRenderer = splitAndOverflowRenderers[1]; overflowRenderer.DeleteOwnProperty(Property.FORCED_PLACEMENT); UpdateHeightsOnSplit(wasHeightClipped, splitRenderer_1, overflowRenderer); - if (IsRelativePosition() && !positionedRenderers.IsEmpty()) { + if (IsRelativePosition() && !positionedRenderers.IsEmpty()) + { overflowRenderer.positionedRenderers = new List(positionedRenderers); } - if (keepTogether) { + if (keepTogether) + { splitRenderer_1 = null; overflowRenderer.SetChildRenderers(GetChildRenderers()); } @@ -286,81 +346,95 @@ internal override LayoutResult ProcessNotFullChildResult(LayoutContext layoutCon ApplyPaddings(occupiedArea.GetBBox(), paddings, true); ApplyBorderBox(occupiedArea.GetBBox(), borders, true); ApplyMargins(occupiedArea.GetBBox(), true); - if (splitRenderer_1 == null || splitRenderer_1.GetChildRenderers().IsEmpty()) { + if (splitRenderer_1 == null || splitRenderer_1.GetChildRenderers().IsEmpty()) + { return new LayoutResult(LayoutResult.NOTHING, null, null, overflowRenderer, result.GetCauseOfNothing()).SetAreaBreak (result.GetAreaBreak()); } - else { - return new LayoutResult(LayoutResult.PARTIAL, layoutContext.GetArea(), splitRenderer_1, overflowRenderer, + else + { + return new LayoutResult(LayoutResult.PARTIAL, layoutContext.GetArea(), splitRenderer_1, overflowRenderer, null).SetAreaBreak(result.GetAreaBreak()); } } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT // TODO DEVSIX-5238 Consider this fix (perhaps it should be improved or unified) while working on the ticket - internal virtual LayoutArea GetOccupiedAreaInCaseNothingWasWrappedWithFull(LayoutResult result, IRenderer - splitRenderer) { + internal virtual LayoutArea GetOccupiedAreaInCaseNothingWasWrappedWithFull(LayoutResult result, IRenderer + splitRenderer) + { return null != result.GetOccupiedArea() ? result.GetOccupiedArea() : splitRenderer.GetOccupiedArea(); } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT - internal override bool StopLayoutingChildrenIfChildResultNotFull(LayoutResult returnResult) { + //\cond DO_NOT_DOCUMENT + internal override bool StopLayoutingChildrenIfChildResultNotFull(LayoutResult returnResult) + { return returnResult.GetStatus() != LayoutResult.FULL; } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT /// internal override void RecalculateOccupiedAreaAfterChildLayout(Rectangle resultBBox, float? blockMaxHeight - ) { + ) + { Rectangle oldBBox = occupiedArea.GetBBox().Clone(); Rectangle recalculatedRectangle = Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), resultBBox); occupiedArea.GetBBox().SetY(recalculatedRectangle.GetY()); occupiedArea.GetBBox().SetHeight(recalculatedRectangle.GetHeight()); - if (oldBBox.GetTop() < occupiedArea.GetBBox().GetTop()) { + if (oldBBox.GetTop() < occupiedArea.GetBBox().GetTop()) + { occupiedArea.GetBBox().DecreaseHeight(occupiedArea.GetBBox().GetTop() - oldBBox.GetTop()); } - if (null != blockMaxHeight && occupiedArea.GetBBox().GetHeight() > ((float)blockMaxHeight)) { + if (null != blockMaxHeight && occupiedArea.GetBBox().GetHeight() > ((float)blockMaxHeight)) + { occupiedArea.GetBBox().MoveUp(occupiedArea.GetBBox().GetHeight() - ((float)blockMaxHeight)); occupiedArea.GetBBox().SetHeight((float)blockMaxHeight); } } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal override MarginsCollapseInfo StartChildMarginsHandling(IRenderer childRenderer, Rectangle layoutBox - , MarginsCollapseHandler marginsCollapseHandler) { + , MarginsCollapseHandler marginsCollapseHandler) + { return marginsCollapseHandler.StartChildMarginsHandling(null, layoutBox); } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal override void DecreaseLayoutBoxAfterChildPlacement(Rectangle layoutBox, LayoutResult result, IRenderer - childRenderer) { - if (FlexUtil.IsColumnDirection(this)) { + childRenderer) + { + if (FlexUtil.IsColumnDirection(this)) + { DecreaseLayoutBoxAfterChildPlacementColumnLayout(layoutBox, childRenderer); } - else { + else + { DecreaseLayoutBoxAfterChildPlacementRowLayout(layoutBox, result, childRenderer); } } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal virtual void DecreaseLayoutBoxAfterChildPlacementRowLayout(Rectangle layoutBox, LayoutResult result - , IRenderer childRenderer) { + , IRenderer childRenderer) + { layoutBox.DecreaseWidth(result.GetOccupiedArea().GetBBox().GetRight() - layoutBox.GetLeft()); layoutBox.SetX(result.GetOccupiedArea().GetBBox().GetRight()); IList line = FindLine(childRenderer); bool isLastInLine = childRenderer.Equals(line[line.Count - 1].GetRenderer()); // If it was the last renderer in line we have to go to the next line (row) - if (isLastInLine) { + if (isLastInLine) + { float minBottom = layoutBox.GetTop(); float minLeft = layoutBox.GetLeft(); float commonWidth = 0; - foreach (FlexItemInfo item in line) { + foreach (FlexItemInfo item in line) + { minLeft = Math.Min(minLeft, item.GetRenderer().GetOccupiedArea().GetBBox().GetLeft() - item.GetRectangle() .GetLeft()); minBottom = Math.Min(minBottom, item.GetRenderer().GetOccupiedArea().GetBBox().GetBottom()); @@ -371,21 +445,24 @@ internal virtual void DecreaseLayoutBoxAfterChildPlacementRowLayout(Rectangle la layoutBox.DecreaseHeight(layoutBox.GetTop() - minBottom); } } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal virtual void DecreaseLayoutBoxAfterChildPlacementColumnLayout(Rectangle layoutBox, IRenderer childRenderer - ) { + ) + { FlexItemInfo childFlexItemInfo = FindFlexItemInfo((AbstractRenderer)childRenderer); layoutBox.DecreaseHeight(childFlexItemInfo.GetRenderer().GetOccupiedArea().GetBBox().GetHeight() + childFlexItemInfo .GetRectangle().GetY()); IList line = FindLine(childRenderer); bool isLastInLine = childRenderer.Equals(line[line.Count - 1].GetRenderer()); // If it was the last renderer in line we have to go to the next line (row) - if (isLastInLine) { + if (isLastInLine) + { float maxWidth = 0; float commonHeight = 0; - foreach (FlexItemInfo item in line) { + foreach (FlexItemInfo item in line) + { maxWidth = Math.Max(maxWidth, item.GetRenderer().GetOccupiedArea().GetBBox().GetWidth() + item.GetRectangle ().GetX()); commonHeight += item.GetRectangle().GetY() + item.GetRenderer().GetOccupiedArea().GetBBox().GetHeight(); @@ -395,15 +472,18 @@ internal virtual void DecreaseLayoutBoxAfterChildPlacementColumnLayout(Rectangle layoutBox.MoveRight(maxWidth); } } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal override Rectangle RecalculateLayoutBoxBeforeChildLayout(Rectangle layoutBox, IRenderer childRenderer - , Rectangle initialLayoutBox) { + , Rectangle initialLayoutBox) + { Rectangle layoutBoxCopy = layoutBox.Clone(); - if (childRenderer is AbstractRenderer) { + if (childRenderer is AbstractRenderer) + { FlexItemInfo childFlexItemInfo = FindFlexItemInfo((AbstractRenderer)childRenderer); - if (childFlexItemInfo != null) { + if (childFlexItemInfo != null) + { layoutBoxCopy.DecreaseWidth(childFlexItemInfo.GetRectangle().GetX()); layoutBoxCopy.MoveRight(childFlexItemInfo.GetRectangle().GetX()); layoutBoxCopy.DecreaseHeight(childFlexItemInfo.GetRectangle().GetY()); @@ -411,36 +491,43 @@ internal override Rectangle RecalculateLayoutBoxBeforeChildLayout(Rectangle layo } return layoutBoxCopy; } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT - internal override void HandleForcedPlacement(bool anythingPlaced) { + //\cond DO_NOT_DOCUMENT + internal override void HandleForcedPlacement(bool anythingPlaced) + { } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT // In (horizontal) FlexContainerRenderer Property.FORCED_PLACEMENT is still valid for other children // so do nothing - internal virtual void SetHypotheticalCrossSize(float? mainSize, float? hypotheticalCrossSize) { + internal virtual void SetHypotheticalCrossSize(float? mainSize, float? hypotheticalCrossSize) + { hypotheticalCrossSizes.Put(mainSize.Value, hypotheticalCrossSize); } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT - internal virtual float? GetHypotheticalCrossSize(float? mainSize) { + //\cond DO_NOT_DOCUMENT + internal virtual float? GetHypotheticalCrossSize(float? mainSize) + { return hypotheticalCrossSizes.Get(mainSize.Value); } -//\endcond + //\endcond /// Apply wrap-reverse property. - private void ApplyWrapReverse() { - if (!IsWrapReverse()) { + private void ApplyWrapReverse() + { + if (!IsWrapReverse()) + { return; } JavaCollectionsUtil.Reverse(lines); IList reorderedRendererList = new List(); - foreach (IList line in lines) { - foreach (FlexItemInfo itemInfo in line) { + foreach (IList line in lines) + { + foreach (FlexItemInfo itemInfo in line) + { reorderedRendererList.Add(itemInfo.GetRenderer()); } } @@ -448,10 +535,14 @@ private void ApplyWrapReverse() { AddAllChildRenderers(reorderedRendererList); } - private FlexItemInfo FindFlexItemInfo(AbstractRenderer renderer) { - foreach (IList line in lines) { - foreach (FlexItemInfo itemInfo in line) { - if (itemInfo.GetRenderer().Equals(renderer)) { + private FlexItemInfo FindFlexItemInfo(AbstractRenderer renderer) + { + foreach (IList line in lines) + { + foreach (FlexItemInfo itemInfo in line) + { + if (itemInfo.GetRenderer().Equals(renderer)) + { return itemInfo; } } @@ -459,10 +550,14 @@ private FlexItemInfo FindFlexItemInfo(AbstractRenderer renderer) { return null; } - private IList FindLine(IRenderer renderer) { - foreach (IList line in lines) { - foreach (FlexItemInfo itemInfo in line) { - if (itemInfo.GetRenderer().Equals(renderer)) { + private IList FindLine(IRenderer renderer) + { + foreach (IList line in lines) + { + foreach (FlexItemInfo itemInfo in line) + { + if (itemInfo.GetRenderer().Equals(renderer)) + { return line; } } @@ -470,45 +565,57 @@ private IList FindLine(IRenderer renderer) { return null; } -//\cond DO_NOT_DOCUMENT - internal override void FixOccupiedAreaIfOverflowedX(OverflowPropertyValue? overflowX, Rectangle layoutBox) { + //\cond DO_NOT_DOCUMENT + internal override void FixOccupiedAreaIfOverflowedX(OverflowPropertyValue? overflowX, Rectangle layoutBox) + { // TODO DEVSIX-5087 Support overflow visible/hidden property correctly return; } -//\endcond + //\endcond /// - public override void AddChild(IRenderer renderer) { + public override void AddChild(IRenderer renderer) + { // TODO DEVSIX-5087 Since overflow-fit is an internal iText overflow value, we do not need to support if // for html/css objects, such as flex. As for now we will set VISIBLE by default, however, while working // on the ticket one may come to some more satifactory approach - renderer.SetProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE); + if (!(renderer is AreaBreakRenderer)) + { + renderer.SetProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE); + } base.AddChild(renderer); } - private static void AddSimulateDiv(AbstractRenderer overflowRenderer, float width) { + private static void AddSimulateDiv(AbstractRenderer overflowRenderer, float width) + { IRenderer fakeOverflowRenderer = new DivRenderer(new Div().SetMinWidth(width).SetMaxWidth(width)); overflowRenderer.AddChildRenderer(fakeOverflowRenderer); } private void FillSplitOverflowRenderersForPartialResult(AbstractRenderer splitRenderer, AbstractRenderer overflowRenderer - , IList line, IRenderer childRenderer, LayoutResult childResult) { + , IList line, IRenderer childRenderer, LayoutResult childResult) + { RestoreHeightForOverflowRenderer(childRenderer, childResult.GetOverflowRenderer()); float occupiedSpace = 0; float maxHeightInLine = 0; bool metChildRendererInLine = false; - foreach (FlexItemInfo itemInfo in line) { + foreach (FlexItemInfo itemInfo in line) + { // Split the line - if (itemInfo.GetRenderer() == childRenderer) { + if (itemInfo.GetRenderer() == childRenderer) + { metChildRendererInLine = true; - if (childResult.GetSplitRenderer() != null) { + if (childResult.GetSplitRenderer() != null) + { splitRenderer.AddChildRenderer(childResult.GetSplitRenderer()); } - if (childResult.GetOverflowRenderer() != null) { + if (childResult.GetOverflowRenderer() != null) + { // Get rid of vertical alignment for item with partial result. For column direction, justify-content // is applied to the entire line, not the single item, so there is no point in getting rid of it - if (!FlexUtil.IsColumnDirection(this)) { - StartContentOnTopOfNewPage(childResult.GetOverflowRenderer(), overflowRenderer); + if (!FlexUtil.IsColumnDirection(this)) + { + SetAlignSelfIfNotStretch(childResult.GetOverflowRenderer()); } overflowRenderer.AddChildRenderer(childResult.GetOverflowRenderer()); } @@ -516,9 +623,12 @@ private void FillSplitOverflowRenderersForPartialResult(AbstractRenderer splitRe maxHeightInLine = Math.Max(maxHeightInLine, itemInfo.GetRectangle().GetY() + childResult.GetOccupiedArea() .GetBBox().GetHeight()); } - else { - if (metChildRendererInLine) { - if (FlexUtil.IsColumnDirection(this)) { + else + { + if (metChildRendererInLine) + { + if (FlexUtil.IsColumnDirection(this)) + { overflowRenderer.AddChildRenderer(itemInfo.GetRenderer()); continue; } @@ -534,36 +644,43 @@ private void FillSplitOverflowRenderersForPartialResult(AbstractRenderer splitRe .GetOccupiedArea().GetPageNumber(), neighbourBbox))); RestoreHeightForOverflowRenderer(itemInfo.GetRenderer(), neighbourLayoutResult.GetOverflowRenderer()); // Handle result - if (neighbourLayoutResult.GetStatus() == LayoutResult.PARTIAL && neighbourLayoutResult.GetSplitRenderer() - != null) { + if (neighbourLayoutResult.GetStatus() == LayoutResult.PARTIAL && neighbourLayoutResult.GetSplitRenderer() + != null) + { splitRenderer.AddChildRenderer(neighbourLayoutResult.GetSplitRenderer()); } - else { - if (neighbourLayoutResult.GetStatus() == LayoutResult.FULL) { + else + { + if (neighbourLayoutResult.GetStatus() == LayoutResult.FULL) + { splitRenderer.AddChildRenderer(itemInfo.GetRenderer()); } } // LayoutResult.NOTHING - if (neighbourLayoutResult.GetOverflowRenderer() != null) { - if (neighbourLayoutResult.GetStatus() == LayoutResult.PARTIAL) { + if (neighbourLayoutResult.GetOverflowRenderer() != null) + { + if (neighbourLayoutResult.GetStatus() == LayoutResult.PARTIAL) + { // Get rid of cross alignment for item with partial result - StartContentOnTopOfNewPage(neighbourLayoutResult.GetOverflowRenderer(), overflowRenderer); + SetAlignSelfIfNotStretch(neighbourLayoutResult.GetOverflowRenderer()); } overflowRenderer.AddChildRenderer(neighbourLayoutResult.GetOverflowRenderer()); } - else { + else + { // Here we might need to still occupy the space on overflow renderer AddSimulateDiv(overflowRenderer, itemInfo.GetRectangle().GetWidth()); } } - else { + else + { // Process all preceeding renderers in the current line // They all were layouted as FULL so add them into split renderer splitRenderer.AddChildRenderer(itemInfo.GetRenderer()); // But we also need to occupy the space on overflow renderer AddSimulateDiv(overflowRenderer, itemInfo.GetRectangle().GetWidth()); // Count the height allowed for the items after the one which was partially layouted - maxHeightInLine = Math.Max(maxHeightInLine, itemInfo.GetRectangle().GetY() + itemInfo.GetRenderer().GetOccupiedAreaBBox + maxHeightInLine = Math.Max(maxHeightInLine, itemInfo.GetRectangle().GetY() + ((AbstractRenderer)itemInfo.GetRenderer()).GetOccupiedAreaBBox ().GetHeight()); } } @@ -572,44 +689,53 @@ private void FillSplitOverflowRenderersForPartialResult(AbstractRenderer splitRe } } - private void StartContentOnTopOfNewPage(IRenderer overflowChildRenderer, AbstractRenderer overflowRenderer - ) { + private void SetAlignSelfIfNotStretch(IRenderer overflowRenderer) + { AlignmentPropertyValue alignItems = (AlignmentPropertyValue)this.GetProperty(Property .ALIGN_ITEMS, AlignmentPropertyValue.STRETCH); - AlignmentPropertyValue alignSelf = (AlignmentPropertyValue)overflowChildRenderer.GetProperty(Property.ALIGN_SELF, alignItems); - if (alignSelf != AlignmentPropertyValue.STRETCH) { - overflowChildRenderer.SetProperty(Property.ALIGN_SELF, AlignmentPropertyValue.START); + if (alignSelf != AlignmentPropertyValue.STRETCH) + { + overflowRenderer.SetProperty(Property.ALIGN_SELF, AlignmentPropertyValue.START); } - overflowRenderer.SetProperty(Property.FLEX_FORCE_START_ON_TOP, true); } - private void RestoreHeightForOverflowRenderer(IRenderer childRenderer, IRenderer overflowRenderer) { - if (overflowRenderer == null) { + private void RestoreHeightForOverflowRenderer(IRenderer childRenderer, IRenderer overflowRenderer) + { + if (overflowRenderer == null) + { return; } // childRenderer is the original renderer we set the height for before the layout // And we need to remove the height from the corresponding overflow renderer Tuple2 curHeights = heights.Get(childRenderer); - if (curHeights.GetFirst() == null) { + if (curHeights.GetFirst() == null) + { overflowRenderer.DeleteOwnProperty(Property.HEIGHT); } - if (curHeights.GetSecond() == null) { + if (curHeights.GetSecond() == null) + { overflowRenderer.DeleteOwnProperty(Property.MIN_HEIGHT); } } private void FindMinMaxWidthIfCorrespondingPropertiesAreNotSet(MinMaxWidth minMaxWidth, AbstractWidthHandler - minMaxWidthHandler) { + minMaxWidthHandler) + { float initialMinWidth = minMaxWidth.GetChildrenMinWidth(); float initialMaxWidth = minMaxWidth.GetChildrenMaxWidth(); - if (lines == null || lines.Count == 1) { + if (lines == null || lines.Count == 1) + { FindMinMaxWidth(initialMinWidth, initialMaxWidth, minMaxWidthHandler, GetChildRenderers()); } - else { - foreach (IList line in lines) { + else + { + foreach (IList line in lines) + { IList childRenderers = new List(); - foreach (FlexItemInfo itemInfo in line) { + foreach (FlexItemInfo itemInfo in line) + { childRenderers.Add(itemInfo.GetRenderer()); } FindMinMaxWidth(initialMinWidth, initialMaxWidth, minMaxWidthHandler, childRenderers); @@ -618,23 +744,29 @@ private void FindMinMaxWidthIfCorrespondingPropertiesAreNotSet(MinMaxWidth minMa } private void FindMinMaxWidth(float initialMinWidth, float initialMaxWidth, AbstractWidthHandler minMaxWidthHandler - , IList childRenderers) { + , IList childRenderers) + { float maxWidth = initialMaxWidth; float minWidth = initialMinWidth; - foreach (IRenderer childRenderer in childRenderers) { + foreach (IRenderer childRenderer in childRenderers) + { MinMaxWidth childMinMaxWidth; childRenderer.SetParent(this); - if (childRenderer is AbstractRenderer) { + if (childRenderer is AbstractRenderer) + { childMinMaxWidth = ((AbstractRenderer)childRenderer).GetMinMaxWidth(); } - else { + else + { childMinMaxWidth = MinMaxWidthUtils.CountDefaultMinMaxWidth(childRenderer); } - if (FlexUtil.IsColumnDirection(this)) { + if (FlexUtil.IsColumnDirection(this)) + { maxWidth = Math.Max(maxWidth, childMinMaxWidth.GetMaxWidth()); minWidth = Math.Max(minWidth, childMinMaxWidth.GetMinWidth()); } - else { + else + { maxWidth += childMinMaxWidth.GetMaxWidth(); minWidth += childMinMaxWidth.GetMinWidth(); } @@ -651,22 +783,27 @@ private void FindMinMaxWidth(float initialMinWidth, float initialMaxWidth, Abstr /// /// otherwise. /// - private bool IsRowReverse() { + private bool IsRowReverse() + { return FlexDirectionPropertyValue.ROW_REVERSE == this.GetProperty(Property.FLEX_DIRECTION , null); } - private bool IsColumnReverse() { + private bool IsColumnReverse() + { return FlexDirectionPropertyValue.COLUMN_REVERSE == this.GetProperty(Property .FLEX_DIRECTION, null); } - private IFlexItemMainDirector CreateMainDirector() { - if (FlexUtil.IsColumnDirection(this)) { + private IFlexItemMainDirector CreateMainDirector() + { + if (FlexUtil.IsColumnDirection(this)) + { return IsColumnReverse() ? (IFlexItemMainDirector)new BottomToTopFlexItemMainDirector() : new TopToBottomFlexItemMainDirector (); } - else { + else + { bool isRtlDirection = BaseDirection.RIGHT_TO_LEFT == this.GetProperty(Property.BASE_DIRECTION , null); flexItemMainDirector = IsRowReverse() ^ isRtlDirection ? (IFlexItemMainDirector)new RtlFlexItemMainDirector @@ -675,37 +812,41 @@ private IFlexItemMainDirector CreateMainDirector() { } } - private IList RetrieveRenderersToOverflow(Rectangle flexContainerBBox) { + private IList RetrieveRenderersToOverflow(Rectangle flexContainerBBox) + { IList renderersToOverflow = new List(); Rectangle layoutContextRectangle = flexContainerBBox.Clone(); - UnitValue unitWidthValue = (UnitValue)this.modelElement.GetProperty(Property.WIDTH); - if (unitWidthValue != null && unitWidthValue.GetValue() < layoutContextRectangle.GetWidth()) { - layoutContextRectangle.SetWidth(unitWidthValue.GetValue()); - } ApplyMarginsBordersPaddings(layoutContextRectangle, false); if (FlexUtil.IsColumnDirection(this) && FlexUtil.GetMainSize(this, layoutContextRectangle) >= layoutContextRectangle - .GetHeight()) { + .GetHeight()) + { float commonLineCrossSize = 0; IList lineCrossSizes = FlexUtil.CalculateColumnDirectionCrossSizes(lines); - for (int i = 0; i < lines.Count; ++i) { + for (int i = 0; i < lines.Count; ++i) + { commonLineCrossSize += lineCrossSizes[i]; - if (i > 0 && commonLineCrossSize > layoutContextRectangle.GetWidth()) { + if (i > 0 && commonLineCrossSize > layoutContextRectangle.GetWidth()) + { IList lineRenderersToOverflow = new List(); - foreach (FlexItemInfo itemInfo in lines[i]) { + foreach (FlexItemInfo itemInfo in lines[i]) + { lineRenderersToOverflow.Add(itemInfo.GetRenderer()); } GetFlexItemMainDirector().ApplyDirectionForLine(lineRenderersToOverflow); - if (IsWrapReverse()) { + if (IsWrapReverse()) + { renderersToOverflow.AddAll(0, lineRenderersToOverflow); } - else { + else + { renderersToOverflow.AddAll(lineRenderersToOverflow); } // Those renderers will be handled in adjustLayoutResultToHandleOverflowRenderers method. // If we leave these children in multi-page fixed-height flex container, renderers // will be drawn to the right outside the container's bounds on the first page // (this logic is expected, but needed for the last page only) - foreach (IRenderer renderer in renderersToOverflow) { + foreach (IRenderer renderer in renderersToOverflow) + { childRenderers.Remove(renderer); } } @@ -715,24 +856,31 @@ private IList RetrieveRenderersToOverflow(Rectangle flexContainerBBox } private void AdjustLayoutResultToHandleOverflowRenderers(LayoutResult result, IList renderersToOverflow - ) { - if (LayoutResult.FULL == result.GetStatus()) { + ) + { + if (LayoutResult.FULL == result.GetStatus()) + { IRenderer splitRenderer = CreateSplitRenderer(LayoutResult.PARTIAL); IRenderer overflowRenderer = CreateOverflowRenderer(LayoutResult.PARTIAL); - foreach (IRenderer childRenderer in renderersToOverflow) { + foreach (IRenderer childRenderer in renderersToOverflow) + { overflowRenderer.AddChild(childRenderer); } - foreach (IRenderer childRenderer in GetChildRenderers()) { + foreach (IRenderer childRenderer in GetChildRenderers()) + { splitRenderer.AddChild(childRenderer); } result.SetStatus(LayoutResult.PARTIAL); result.SetSplitRenderer(splitRenderer); result.SetOverflowRenderer(overflowRenderer); } - if (LayoutResult.PARTIAL == result.GetStatus()) { + if (LayoutResult.PARTIAL == result.GetStatus()) + { IRenderer overflowRenderer = result.GetOverflowRenderer(); - foreach (IRenderer childRenderer in renderersToOverflow) { - if (!overflowRenderer.GetChildRenderers().Contains(childRenderer)) { + foreach (IRenderer childRenderer in renderersToOverflow) + { + if (!overflowRenderer.GetChildRenderers().Contains(childRenderer)) + { overflowRenderer.AddChild(childRenderer); } } diff --git a/itext/itext.layout/itext/layout/renderer/FlexItemInfo.cs b/itext/itext.layout/itext/layout/renderer/FlexItemInfo.cs index ea59761ff..92af35bad 100644 --- a/itext/itext.layout/itext/layout/renderer/FlexItemInfo.cs +++ b/itext/itext.layout/itext/layout/renderer/FlexItemInfo.cs @@ -22,25 +22,30 @@ You should have received a copy of the GNU Affero General Public License */ using iText.Kernel.Geom; -namespace iText.Layout.Renderer { -//\cond DO_NOT_DOCUMENT - internal class FlexItemInfo { - private AbstractRenderer renderer; +namespace iText.Layout.Renderer +{ + //\cond DO_NOT_DOCUMENT + internal class FlexItemInfo + { + private IRenderer renderer; private Rectangle rectangle; - public FlexItemInfo(AbstractRenderer renderer, Rectangle rectangle) { + public FlexItemInfo(IRenderer renderer, Rectangle rectangle) + { this.renderer = renderer; this.rectangle = rectangle; } - public virtual AbstractRenderer GetRenderer() { + public virtual IRenderer GetRenderer() + { return renderer; } - public virtual Rectangle GetRectangle() { + public virtual Rectangle GetRectangle() + { return rectangle; } } -//\endcond + //\endcond } diff --git a/itext/itext.layout/itext/layout/renderer/FlexUtil.cs b/itext/itext.layout/itext/layout/renderer/FlexUtil.cs index 755639af0..6f9c4364c 100644 --- a/itext/itext.layout/itext/layout/renderer/FlexUtil.cs +++ b/itext/itext.layout/itext/layout/renderer/FlexUtil.cs @@ -30,10 +30,13 @@ You should have received a copy of the GNU Affero General Public License using iText.Layout.Layout; using iText.Layout.Minmaxwidth; using iText.Layout.Properties; +using iText.Layout.Element; -namespace iText.Layout.Renderer { -//\cond DO_NOT_DOCUMENT - internal sealed class FlexUtil { +namespace iText.Layout.Renderer +{ + //\cond DO_NOT_DOCUMENT + internal sealed class FlexUtil + { private const float EPSILON = 0.0001F; private const float FLEX_GROW_INITIAL_VALUE = 0F; @@ -42,7 +45,8 @@ internal sealed class FlexUtil { private static readonly ILogger logger = ITextLogManager.GetLogger(typeof(iText.Layout.Renderer.FlexUtil)); - private FlexUtil() { + private FlexUtil() + { } // Do nothing @@ -57,7 +61,8 @@ private FlexUtil() { /// flex container's renderer /// list of lines public static IList> CalculateChildrenRectangles(Rectangle flexContainerBBox, FlexContainerRenderer - flexContainerRenderer) { + flexContainerRenderer) + { Rectangle layoutBox = flexContainerBBox.Clone(); flexContainerRenderer.ApplyMarginsBordersPaddings(layoutBox, false); // 9.2. Line Length Determination @@ -69,9 +74,6 @@ public static IList> CalculateChildrenRectangles(Rectangle f // We need to have crossSize only if its value is definite. float?[] crossSizes = GetCrossSizes(flexContainerRenderer, layoutBox); float? crossSize = crossSizes[0]; - if (crossSize == null && IsColumnDirection(flexContainerRenderer)) { - crossSize = layoutBox.GetWidth(); - } float? minCrossSize = crossSizes[1]; float? maxCrossSize = crossSizes[2]; float layoutBoxCrossSize = IsColumnDirection(flexContainerRenderer) ? layoutBox.GetWidth() : layoutBox.GetHeight @@ -95,20 +97,24 @@ public static IList> CalculateChildrenRectangles(Rectangle f // First, calculate max line size. For column container it should be the default size if width is not set. // For row container it is not used currently. float maxHypotheticalMainSize = 0; - foreach (IList line in lines) { + foreach (IList line in lines) + { float hypotheticalMainSizesSum = 0; - foreach (FlexUtil.FlexItemCalculationInfo info in line) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { hypotheticalMainSizesSum += info.GetOuterMainSize(info.hypotheticalMainSize); } maxHypotheticalMainSize = Math.Max(maxHypotheticalMainSize, hypotheticalMainSizesSum); } float containerMainSize = GetMainSize(flexContainerRenderer, new Rectangle(IsColumnDirection(flexContainerRenderer - ) ? 0 : maxHypotheticalMainSize, IsColumnDirection(flexContainerRenderer) ? maxHypotheticalMainSize : + ) ? 0 : maxHypotheticalMainSize, IsColumnDirection(flexContainerRenderer) ? maxHypotheticalMainSize : 0)); - if (IsColumnDirection(flexContainerRenderer)) { + if (IsColumnDirection(flexContainerRenderer)) + { ResolveFlexibleLengths(lines, layoutBox.GetHeight(), containerMainSize); } - else { + else + { ResolveFlexibleLengths(lines, mainSize); } // 9.4. Cross Size Determination @@ -143,9 +149,11 @@ public static IList> CalculateChildrenRectangles(Rectangle f ApplyAlignContent(lines, flexContainerRenderer, crossSize, layoutBox); // Convert FlexItemCalculationInfo's into FlexItemInfo's IList> layoutTable = new List>(); - foreach (IList line in lines) { + foreach (IList line in lines) + { IList layoutLine = new List(); - foreach (FlexUtil.FlexItemCalculationInfo info in line) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { layoutLine.Add(new FlexItemInfo(info.renderer, info.ToRectangle())); } layoutTable.Add(layoutLine); @@ -154,116 +162,118 @@ public static IList> CalculateChildrenRectangles(Rectangle f } private static void ApplyAlignContent(IList> lines, FlexContainerRenderer - renderer, float? crossSize, Rectangle layoutBox) { + renderer, float? crossSize, Rectangle layoutBox) + { AlignContentPropertyValue alignContent = (AlignContentPropertyValue)renderer.GetProperty(Property.ALIGN_CONTENT, AlignContentPropertyValue.NORMAL); - bool isFirstFlexStart = (bool)renderer.GetProperty(Property.FLEX_FORCE_START_ON_TOP, false); - if (crossSize != null) { - if (renderer.IsWrapReverse()) { + if (crossSize != null) + { + if (renderer.IsWrapReverse()) + { JavaCollectionsUtil.Reverse(lines); } - float boxSize; - float freeSpace; - if (IsColumnDirection(renderer)) { - boxSize = Math.Min(layoutBox.GetWidth(), (float)crossSize); - } - else { - boxSize = Math.Min(layoutBox.GetHeight(), (float)crossSize); - } float lineCrossSize = 0; - int columnsOnPage = 0; - foreach (IList line in lines) { + foreach (IList line in lines) + { float maxItemSize = GetItemMaxCrossSize(line); - if (IsColumnDirection(renderer)) { - if (lineCrossSize + maxItemSize <= boxSize) { - lineCrossSize += maxItemSize; - columnsOnPage++; - } - else { - break; - } - } - else { - lineCrossSize += maxItemSize; - } + lineCrossSize += maxItemSize; } - freeSpace = boxSize - lineCrossSize; - ApplyAlignContent(lines, IsColumnDirection(renderer) ? columnsOnPage : lines.Count, alignContent, freeSpace - < 0 ? 0 : freeSpace, IsColumnDirection(renderer), isFirstFlexStart); - if (renderer.IsWrapReverse()) { + float freeSpace; + if (IsColumnDirection(renderer)) + { + freeSpace = Math.Min(layoutBox.GetWidth(), (float)crossSize) - lineCrossSize; + } + else + { + freeSpace = Math.Min(layoutBox.GetHeight(), (float)crossSize) - lineCrossSize; + } + ApplyAlignContent(lines, alignContent, freeSpace, IsColumnDirection(renderer)); + if (renderer.IsWrapReverse()) + { JavaCollectionsUtil.Reverse(lines); } } } - private static void ApplyAlignContent(IList> lines, int linesOnPage - , AlignContentPropertyValue alignContent, float freeSpace, bool isColumnDirection, bool isFirstFlexStart - ) { - if (!lines.IsEmpty()) { - switch (alignContent) { - case AlignContentPropertyValue.CENTER: { - ApplyCenterAlignment(lines, freeSpace, isColumnDirection, isFirstFlexStart); - break; - } + private static void ApplyAlignContent(IList> lines, AlignContentPropertyValue + alignContent, float freeSpace, bool isColumnDirection) + { + if (!lines.IsEmpty()) + { + switch (alignContent) + { + case AlignContentPropertyValue.CENTER: + { + ApplyCentralAlignment(lines, freeSpace, isColumnDirection); + break; + } case AlignContentPropertyValue.FLEX_END: - case AlignContentPropertyValue.END: { - ApplyFlexEndAlignment(lines, freeSpace, isColumnDirection, isFirstFlexStart); - break; - } + { + ApplyFlexEndAlignment(lines, freeSpace, isColumnDirection); + break; + } - case AlignContentPropertyValue.SPACE_BETWEEN: { - ApplySpaceBetweenAlignment(lines, linesOnPage, freeSpace, isColumnDirection); - break; - } + case AlignContentPropertyValue.SPACE_BETWEEN: + { + ApplySpaceBetweenAlignment(lines, freeSpace, isColumnDirection); + break; + } - case AlignContentPropertyValue.SPACE_AROUND: { - ApplySpaceAroundAlignment(lines, linesOnPage, freeSpace, isColumnDirection, isFirstFlexStart); - break; - } + case AlignContentPropertyValue.SPACE_AROUND: + { + ApplySpaceAroundAlignment(lines, freeSpace, isColumnDirection); + break; + } - case AlignContentPropertyValue.SPACE_EVENLY: { - ApplySpaceEvenlyAlignment(lines, linesOnPage, freeSpace, isColumnDirection, isFirstFlexStart); - break; - } + case AlignContentPropertyValue.SPACE_EVENLY: + { + ApplySpaceEvenlyAlignment(lines, freeSpace, isColumnDirection); + break; + } case AlignContentPropertyValue.FLEX_START: - case AlignContentPropertyValue.START: - default: { - break; - } + default: + { + break; + } } } } // We don't need to do anything in these cases private static void ApplyFlexEndAlignment(IList> lines, float freeSpace - , bool isColumnDirection, bool isFirstFlexStart) { - if (isFirstFlexStart && lines.Count < 2) { - return; - } - IList targetLine = isFirstFlexStart && lines.Count > 1 ? lines[1] : lines - [0]; - foreach (FlexUtil.FlexItemCalculationInfo item in targetLine) { - if (isColumnDirection) { + , bool isColumnDirection) + { + foreach (FlexUtil.FlexItemCalculationInfo item in lines[0]) + { + if (isColumnDirection) + { item.xShift = freeSpace; } - else { + else + { item.yShift = freeSpace; } } } - private static void ApplySpaceBetweenAlignment(IList> lines, int linesOnPage - , float freeSpace, bool isColumnDirection) { - if (linesOnPage > 1) { - float indentation = freeSpace / (linesOnPage - 1); - for (int i = 1; i < linesOnPage; i++) { - foreach (FlexUtil.FlexItemCalculationInfo item in lines[i]) { - if (isColumnDirection) { + private static void ApplySpaceBetweenAlignment(IList> lines, float + freeSpace, bool isColumnDirection) + { + if (lines.Count != 1) + { + float indentation = freeSpace / (lines.Count - 1); + for (int i = 1; i < lines.Count; i++) + { + foreach (FlexUtil.FlexItemCalculationInfo item in lines[i]) + { + if (isColumnDirection) + { item.xShift = indentation; } - else { + else + { item.yShift = indentation; } } @@ -271,88 +281,115 @@ private static void ApplySpaceBetweenAlignment(IList> lines, int linesOnPage - , float freeSpace, bool isColumnDirection, bool isFirstFlexStart) { - float indentation = freeSpace / (linesOnPage + 1); - int startIndex = isFirstFlexStart ? 1 : 0; - for (int i = startIndex; i < linesOnPage; i++) { - foreach (FlexUtil.FlexItemCalculationInfo item in lines[i]) { - if (isColumnDirection) { + private static void ApplySpaceEvenlyAlignment(IList> lines, float + freeSpace, bool isColumnDirection) + { + float indentation = freeSpace / (lines.Count + 1); + foreach (IList line in lines) + { + foreach (FlexUtil.FlexItemCalculationInfo item in line) + { + if (isColumnDirection) + { item.xShift = indentation; } - else { + else + { item.yShift = indentation; } } } } - private static void ApplySpaceAroundAlignment(IList> lines, int linesOnPage - , float freeSpace, bool isColumnDirection, bool isFirstFlexStart) { - int startIndex = isFirstFlexStart ? 1 : 0; - float indentation = freeSpace / linesOnPage; - for (int i = startIndex; i < linesOnPage; i++) { - float shift = (i == 0) ? (indentation / 2) : indentation; - foreach (FlexUtil.FlexItemCalculationInfo item in lines[i]) { - if (isColumnDirection) { - item.xShift = shift; - } - else { - item.yShift = shift; + private static void ApplySpaceAroundAlignment(IList> lines, float + freeSpace, bool isColumnDirection) + { + float indentation = freeSpace / lines.Count; + foreach (FlexUtil.FlexItemCalculationInfo item in lines[0]) + { + if (isColumnDirection) + { + item.xShift = indentation / 2; + } + else + { + item.yShift = indentation / 2; + } + } + if (lines.Count != 1) + { + for (int i = 1; i < lines.Count; i++) + { + foreach (FlexUtil.FlexItemCalculationInfo item in lines[i]) + { + if (isColumnDirection) + { + item.xShift = indentation; + } + else + { + item.yShift = indentation; + } } } } } - private static void ApplyCenterAlignment(IList> lines, float freeSpace - , bool isColumnDirection, bool isFirstFlexStart) { - if (isFirstFlexStart && lines.Count < 2) { - return; - } - float indentation = freeSpace / 2; - int targetIndex = isFirstFlexStart && lines.Count > 1 ? 1 : 0; - foreach (FlexUtil.FlexItemCalculationInfo item in lines[targetIndex]) { - if (isColumnDirection) { - item.xShift = indentation; + private static void ApplyCentralAlignment(IList> lines, float freeSpace + , bool isColumnDirection) + { + foreach (FlexUtil.FlexItemCalculationInfo item in lines[0]) + { + if (isColumnDirection) + { + item.xShift = freeSpace / 2; } - else { - item.yShift = indentation; + else + { + item.yShift = freeSpace / 2; } } } - private static float GetItemMaxCrossSize(IList line) { + private static float GetItemMaxCrossSize(IList line) + { float maxItemSize = 0; - foreach (FlexUtil.FlexItemCalculationInfo item in line) { - if (item.GetOuterCrossSize(item.crossSize) > maxItemSize) { + foreach (FlexUtil.FlexItemCalculationInfo item in line) + { + if (item.GetOuterCrossSize(item.crossSize) > maxItemSize) + { maxItemSize = item.GetOuterCrossSize(item.crossSize); } } return maxItemSize; } -//\cond DO_NOT_DOCUMENT - internal static bool IsColumnDirection(FlexContainerRenderer renderer) { + //\cond DO_NOT_DOCUMENT + internal static bool IsColumnDirection(FlexContainerRenderer renderer) + { FlexDirectionPropertyValue flexDir = (FlexDirectionPropertyValue)renderer.GetProperty(Property.FLEX_DIRECTION, FlexDirectionPropertyValue.ROW); return FlexDirectionPropertyValue.COLUMN == flexDir || FlexDirectionPropertyValue.COLUMN_REVERSE == flexDir; } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT - internal static float GetMainSize(FlexContainerRenderer renderer, Rectangle layoutBox) { + //\cond DO_NOT_DOCUMENT + internal static float GetMainSize(FlexContainerRenderer renderer, Rectangle layoutBox) + { bool isColumnDirection = IsColumnDirection(renderer); float layoutBoxMainSize; float? mainSize; float? maxDimension = null; float? minDimension = null; - if (isColumnDirection) { + if (isColumnDirection) + { layoutBoxMainSize = layoutBox.GetHeight(); mainSize = renderer.RetrieveHeight(); maxDimension = ResolveUnitValue(renderer, Property.MAX_HEIGHT, layoutBoxMainSize); minDimension = ResolveUnitValue(renderer, Property.MIN_HEIGHT, layoutBoxMainSize); } - else { + else + { layoutBoxMainSize = layoutBox.GetWidth(); mainSize = renderer.RetrieveWidth(layoutBoxMainSize); maxDimension = ResolveUnitValue(renderer, Property.MAX_WIDTH, layoutBoxMainSize); @@ -361,42 +398,51 @@ internal static float GetMainSize(FlexContainerRenderer renderer, Rectangle layo // TODO DEVSIX-5001 min-content and max-content as width are not supported // if that dimension of the flex container is being sized under a min or max-content constraint, // the available space in that dimension is that constraint; - if (mainSize == null) { + if (mainSize == null) + { mainSize = layoutBoxMainSize; } - if (minDimension != null && minDimension > mainSize) { + if (minDimension != null && minDimension > mainSize) + { mainSize = minDimension; } if (maxDimension != null && (minDimension == null || maxDimension > minDimension) && maxDimension < mainSize - ) { + ) + { mainSize = maxDimension; } return (float)mainSize; } -//\endcond + //\endcond - private static float? ResolveUnitValue(FlexContainerRenderer renderer, int property, float baseValue) { + private static float? ResolveUnitValue(FlexContainerRenderer renderer, int property, float baseValue) + { UnitValue value = renderer.GetPropertyAsUnitValue(property); - if (value == null) { + if (value == null) + { return null; } - if (value.IsPercentValue()) { + if (value.IsPercentValue()) + { return value.GetValue() / 100 * baseValue; } return value.GetValue(); } - private static float?[] GetCrossSizes(FlexContainerRenderer renderer, Rectangle layoutBox) { + private static float?[] GetCrossSizes(FlexContainerRenderer renderer, Rectangle layoutBox) + { bool isColumnDirection = IsColumnDirection(renderer); return new float?[] { isColumnDirection ? renderer.RetrieveWidth(layoutBox.GetWidth()) : renderer.RetrieveHeight (), isColumnDirection ? renderer.RetrieveMinWidth(layoutBox.GetWidth()) : renderer.RetrieveMinHeight() , isColumnDirection ? renderer.RetrieveMaxWidth(layoutBox.GetWidth()) : renderer.RetrieveMaxHeight() }; } -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal static void DetermineFlexBasisAndHypotheticalMainSizeForFlexItems(IList flexItemCalculationInfos, float crossSize, bool isColumnDirection) { - foreach (FlexUtil.FlexItemCalculationInfo info in flexItemCalculationInfos) { + > flexItemCalculationInfos, float crossSize, bool isColumnDirection) + { + foreach (FlexUtil.FlexItemCalculationInfo info in flexItemCalculationInfos) + { // 3. Determine the flex base size and hypothetical main size of each item: AbstractRenderer renderer = info.renderer; // TODO DEVSIX-5001 content as width are not supported @@ -407,15 +453,18 @@ internal static void DetermineFlexBasisAndHypotheticalMainSizeForFlexItems(IList // then the flex base size is calculated from its inner cross size // and the flex item’s intrinsic aspect ratio. float? definiteCrossSize = null; - if (renderer.HasAspectRatio()) { + if (renderer.HasAspectRatio()) + { definiteCrossSize = isColumnDirection ? renderer.RetrieveWidth(crossSize) : renderer.RetrieveHeight(); } - if (info.flexBasisContent && definiteCrossSize != null) { + if (info.flexBasisContent && definiteCrossSize != null) + { float aspectRatio = (float)renderer.GetAspectRatio(); - info.flexBaseSize = isColumnDirection ? (float)definiteCrossSize / aspectRatio : (float)definiteCrossSize + info.flexBaseSize = isColumnDirection ? (float)definiteCrossSize / aspectRatio : (float)definiteCrossSize * aspectRatio; } - else { + else + { // A. If the item has a definite used flex basis, that’s the flex base size. info.flexBaseSize = info.flexBasis; } @@ -444,72 +493,89 @@ internal static void DetermineFlexBasisAndHypotheticalMainSizeForFlexItems(IList info.mainSize = info.hypotheticalMainSize; } } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT // Note: We assume that it was resolved on some upper level // 4. Determine the main size of the flex container internal static IList> CollectFlexItemsIntoFlexLines(IList flexItemCalculationInfos, float mainSize, bool isSingleLine) { + > flexItemCalculationInfos, float mainSize, bool isSingleLine) + { IList> lines = new List>(); IList currentLineInfos = new List(); - if (isSingleLine) { + if (isSingleLine) + { currentLineInfos.AddAll(flexItemCalculationInfos); } - else { + else + { float occupiedLineSpace = 0; - foreach (FlexUtil.FlexItemCalculationInfo info in flexItemCalculationInfos) { + foreach (FlexUtil.FlexItemCalculationInfo info in flexItemCalculationInfos) + { occupiedLineSpace += info.GetOuterMainSize(info.hypotheticalMainSize); - if (occupiedLineSpace > mainSize + EPSILON) { + if (occupiedLineSpace > mainSize + EPSILON) + { // If the very first uncollected item wouldn’t fit, collect just it into the line. - if (currentLineInfos.IsEmpty()) { + if (currentLineInfos.IsEmpty()) + { currentLineInfos.Add(info); lines.Add(currentLineInfos); currentLineInfos = new List(); occupiedLineSpace = 0; } - else { + else + { lines.Add(currentLineInfos); currentLineInfos = new List(); currentLineInfos.Add(info); occupiedLineSpace = info.GetOuterMainSize(info.hypotheticalMainSize); } } - else { + else + { currentLineInfos.Add(info); } } } // the last line should be added - if (!currentLineInfos.IsEmpty()) { + if (!currentLineInfos.IsEmpty()) + { lines.Add(currentLineInfos); } return lines; } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal static void ResolveFlexibleLengths(IList> lines, float mainSize - ) { - foreach (IList line in lines) { + ) + { + foreach (IList line in lines) + { // 1. Determine the used flex factor. float hypotheticalMainSizesSum = 0; - foreach (FlexUtil.FlexItemCalculationInfo info in line) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { hypotheticalMainSizesSum += info.GetOuterMainSize(info.hypotheticalMainSize); } // if the sum is less than the flex container’s inner main size, // use the flex grow factor for the rest of this algorithm; otherwise, use the flex shrink factor. bool isFlexGrow = hypotheticalMainSizesSum < mainSize; // 2. Size inflexible items. - foreach (FlexUtil.FlexItemCalculationInfo info in line) { - if (isFlexGrow) { - if (IsZero(info.flexGrow) || info.flexBaseSize > info.hypotheticalMainSize) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { + if (isFlexGrow) + { + if (IsZero(info.flexGrow) || info.flexBaseSize > info.hypotheticalMainSize) + { info.mainSize = info.hypotheticalMainSize; info.isFrozen = true; } } - else { - if (IsZero(info.flexShrink) || info.flexBaseSize < info.hypotheticalMainSize) { + else + { + if (IsZero(info.flexShrink) || info.flexBaseSize < info.hypotheticalMainSize) + { info.mainSize = info.hypotheticalMainSize; info.isFrozen = true; } @@ -519,12 +585,15 @@ internal static void ResolveFlexibleLengths(IList Math.Abs(initialFreeSpace * flexFactorSum)) { + if (flexFactorSum < 1 && Math.Abs(remainingFreeSpace) > Math.Abs(initialFreeSpace * flexFactorSum)) + { remainingFreeSpace = initialFreeSpace * flexFactorSum; } // c. Distribute free space proportional to the flex factors - if (!IsZero(remainingFreeSpace)) { + if (!IsZero(remainingFreeSpace)) + { float scaledFlexShrinkFactorsSum = 0; - foreach (FlexUtil.FlexItemCalculationInfo info in line) { - if (!info.isFrozen) { - if (isFlexGrow) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { + if (!info.isFrozen) + { + if (isFlexGrow) + { float ratio = info.flexGrow / flexFactorSum; info.mainSize = info.flexBaseSize + remainingFreeSpace * ratio; } - else { + else + { info.scaledFlexShrinkFactor = info.flexShrink * info.flexBaseSize; scaledFlexShrinkFactorsSum += info.scaledFlexShrinkFactor; } } } - if (!IsZero(scaledFlexShrinkFactorsSum)) { - foreach (FlexUtil.FlexItemCalculationInfo info in line) { - if (!info.isFrozen && !isFlexGrow) { + if (!IsZero(scaledFlexShrinkFactorsSum)) + { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { + if (!info.isFrozen && !isFlexGrow) + { float ratio = info.scaledFlexShrinkFactor / scaledFlexShrinkFactorsSum; info.mainSize = info.flexBaseSize - Math.Abs(remainingFreeSpace) * ratio; } } } } - else { + else + { // This is not mentioned in the algo, however we must initialize main size (target main size) - foreach (FlexUtil.FlexItemCalculationInfo info in line) { - if (!info.isFrozen) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { + if (!info.isFrozen) + { info.mainSize = info.flexBaseSize; } } } // d. Fix min/max violations. float sum = 0; - foreach (FlexUtil.FlexItemCalculationInfo info in line) { - if (!info.isFrozen) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { + if (!info.isFrozen) + { // Clamp each non-frozen item’s target main size by its used min and max main sizes // and floor its content-box size at zero. float clampedSize = Math.Min(Math.Max(info.mainSize, info.minContent), info.maxContent); - if (info.mainSize > clampedSize) { + if (info.mainSize > clampedSize) + { info.isMaxViolated = true; } - else { - if (info.mainSize < clampedSize) { + else + { + if (info.mainSize < clampedSize) + { info.isMinViolated = true; } } @@ -586,9 +672,12 @@ internal static void ResolveFlexibleLengths(IList sum && info.isMaxViolated)) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { + if (!info.isFrozen) + { + if (IsZero(sum) || (0 < sum && info.isMinViolated) || (0 > sum && info.isMaxViolated)) + { info.isFrozen = true; } } @@ -596,7 +685,7 @@ internal static void ResolveFlexibleLengths(IList> lines, float layoutBoxSize - , float containerSize) { + , float containerSize) + { ResolveFlexibleLengths(lines, containerSize); - if (lines.Count == 1 && layoutBoxSize < containerSize - EPSILON) { + if (lines.Count == 1 && layoutBoxSize < containerSize - EPSILON) + { IList lineToRecalculate = new List(); float mainSize = 0; - foreach (FlexUtil.FlexItemCalculationInfo itemInfo in lines[0]) { + foreach (FlexUtil.FlexItemCalculationInfo itemInfo in lines[0]) + { mainSize += itemInfo.GetOuterMainSize(itemInfo.mainSize); - if (mainSize < layoutBoxSize - EPSILON) { + if (mainSize < layoutBoxSize - EPSILON) + { itemInfo.isFrozen = false; lineToRecalculate.Add(itemInfo); } - else { + else + { break; } } - if (lineToRecalculate.Count > 0) { + if (lineToRecalculate.Count > 0) + { IList> updatedLines = new List>(); updatedLines.Add(lineToRecalculate); @@ -630,36 +725,45 @@ private static void ResolveFlexibleLengths(IList> lines, bool isColumnDirection, float crossSize) { - foreach (IList line in lines) { - foreach (FlexUtil.FlexItemCalculationInfo info in line) { + >> lines, bool isColumnDirection, float crossSize) + { + foreach (IList line in lines) + { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { DetermineHypotheticalCrossSizeForFlexItem(info, isColumnDirection, crossSize); } } } -//\endcond + //\endcond - private static void DetermineHypotheticalCrossSizeForFlexItem(FlexUtil.FlexItemCalculationInfo info, bool - isColumnDirection, float crossSize) { + private static void DetermineHypotheticalCrossSizeForFlexItem(FlexUtil.FlexItemCalculationInfo info, bool + isColumnDirection, float crossSize) + { if (info.renderer is FlexContainerRenderer && ((FlexContainerRenderer)info.renderer).GetHypotheticalCrossSize - (info.mainSize) != null) { + (info.mainSize) != null) + { // Take from cache info.hypotheticalCrossSize = ((FlexContainerRenderer)info.renderer).GetHypotheticalCrossSize(info.mainSize ).Value; } - else { - if (isColumnDirection) { + else + { + if (isColumnDirection) + { MinMaxWidth minMaxWidth = info.renderer.GetMinMaxWidth(crossSize); info.hypotheticalCrossSize = info.GetInnerCrossSize(Math.Max(Math.Min(minMaxWidth.GetMaxWidth(), crossSize ), minMaxWidth.GetMinWidth())); // Cache hypotheticalCrossSize for FlexContainerRenderer - if (info.renderer is FlexContainerRenderer) { + if (info.renderer is FlexContainerRenderer) + { ((FlexContainerRenderer)info.renderer).SetHypotheticalCrossSize(info.mainSize, info.hypotheticalCrossSize); } } - else { + else + { UnitValue prevMainSize = info.renderer.ReplaceOwnProperty(Property.WIDTH, UnitValue.CreatePointValue (info.mainSize)); UnitValue prevMinMainSize = info.renderer.ReplaceOwnProperty(Property.MIN_WIDTH, null); @@ -669,14 +773,17 @@ private static void DetermineHypotheticalCrossSizeForFlexItem(FlexUtil.FlexItemC info.renderer.ReturnBackOwnProperty(Property.MIN_WIDTH, prevMinMainSize); info.renderer.ReturnBackOwnProperty(Property.WIDTH, prevMainSize); // Since main size is clamped with min-width, we do expect the result to be full - if (result.GetStatus() == LayoutResult.FULL) { + if (result.GetStatus() == LayoutResult.FULL) + { info.hypotheticalCrossSize = info.GetInnerCrossSize(result.GetOccupiedArea().GetBBox().GetHeight()); // Cache hypotheticalCrossSize for FlexContainerRenderer - if (info.renderer is FlexContainerRenderer) { + if (info.renderer is FlexContainerRenderer) + { ((FlexContainerRenderer)info.renderer).SetHypotheticalCrossSize(info.mainSize, info.hypotheticalCrossSize); } } - else { + else + { logger.LogError(iText.IO.Logs.IoLogMessageConstant.FLEX_ITEM_LAYOUT_RESULT_IS_NOT_FULL); info.hypotheticalCrossSize = 0; } @@ -684,13 +791,16 @@ private static void DetermineHypotheticalCrossSizeForFlexItem(FlexUtil.FlexItemC } } -//\cond DO_NOT_DOCUMENT - internal static IList CalculateColumnDirectionCrossSizes(IList> lines) { + //\cond DO_NOT_DOCUMENT + internal static IList CalculateColumnDirectionCrossSizes(IList> lines) + { IList lineCrossSizes = new List(); - foreach (IList line in lines) { + foreach (IList line in lines) + { float flexLinesCrossSize = 0; float largestCrossSize = 0; - foreach (FlexItemInfo info in line) { + foreach (FlexItemInfo info in line) + { // TODO DEVSIX-5002 Flex items whose cross-axis margins are both auto shouldn't be collected // TODO DEVSIX-5038 Support BASELINE as align-self largestCrossSize = Math.Max(largestCrossSize, info.GetRectangle().GetWidth()); @@ -700,21 +810,26 @@ internal static IList CalculateColumnDirectionCrossSizes(IList CalculateCrossSizeOfEachFlexLine(IList> lines, float? minCrossSize, float? crossSize, float? maxCrossSize) { + >> lines, float? minCrossSize, float? crossSize, float? maxCrossSize) + { bool isSingleLine = lines.Count == 1; IList lineCrossSizes = new List(); - if (isSingleLine && crossSize != null) { + if (isSingleLine && crossSize != null) + { lineCrossSizes.Add((float)crossSize); } - else { - foreach (IList line in lines) { + else + { + foreach (IList line in lines) + { float flexLinesCrossSize = 0; float largestHypotheticalCrossSize = 0; - foreach (FlexUtil.FlexItemCalculationInfo info in line) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { // 1. Collect all the flex items whose inline-axis is parallel to the main-axis, // whose align-self is baseline, and whose cross-axis margins are both non-auto. // Find the largest of the distances between each item’s baseline and @@ -724,18 +839,22 @@ internal static IList CalculateCrossSizeOfEachFlexLine(IList CalculateCrossSizeOfEachFlexLine(IList> lines, float? crossSize, IList lineCrossSizes, Rectangle layoutBox) { + >> lines, float? crossSize, IList lineCrossSizes, Rectangle layoutBox) + { AlignContentPropertyValue alignContent = (AlignContentPropertyValue)flexContainerRenderer.GetProperty(Property.ALIGN_CONTENT, AlignContentPropertyValue.STRETCH); - if (crossSize != null && alignContent == AlignContentPropertyValue.STRETCH) { + if (crossSize != null && alignContent == AlignContentPropertyValue.STRETCH) + { // Line order becomes important for alignment - if (flexContainerRenderer.IsWrapReverse()) { + if (flexContainerRenderer.IsWrapReverse()) + { JavaCollectionsUtil.Reverse(lineCrossSizes); JavaCollectionsUtil.Reverse(lines); } IList currentPageLineCrossSizes = RetrieveCurrentPageLineCrossSizes(flexContainerRenderer, lines, lineCrossSizes , crossSize, layoutBox); - if (currentPageLineCrossSizes.Count > 0) { + if (currentPageLineCrossSizes.Count > 0) + { float flexLinesCrossSizesSum = 0; - foreach (float size in currentPageLineCrossSizes) { + foreach (float size in currentPageLineCrossSizes) + { flexLinesCrossSizesSum += size; } - if (flexLinesCrossSizesSum < crossSize - EPSILON) { + if (flexLinesCrossSizesSum < crossSize - EPSILON) + { float addition = ((float)crossSize - flexLinesCrossSizesSum) / currentPageLineCrossSizes.Count; - for (int i = 0; i < currentPageLineCrossSizes.Count; i++) { + for (int i = 0; i < currentPageLineCrossSizes.Count; i++) + { lineCrossSizes[i] = lineCrossSizes[i] + addition; } } } // Reverse back - if (flexContainerRenderer.IsWrapReverse()) { + if (flexContainerRenderer.IsWrapReverse()) + { JavaCollectionsUtil.Reverse(lineCrossSizes); JavaCollectionsUtil.Reverse(lines); } } } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal static void DetermineUsedCrossSizeOfEachFlexItem(IList> lines - , IList lineCrossSizes, FlexContainerRenderer flexContainerRenderer) { + , IList lineCrossSizes, FlexContainerRenderer flexContainerRenderer) + { bool isColumnDirection = IsColumnDirection(flexContainerRenderer); AlignmentPropertyValue alignItems = (AlignmentPropertyValue)flexContainerRenderer.GetProperty(Property.ALIGN_ITEMS, AlignmentPropertyValue.STRETCH); System.Diagnostics.Debug.Assert(lines.Count == lineCrossSizes.Count); - for (int i = 0; i < lines.Count; i++) { - foreach (FlexUtil.FlexItemCalculationInfo info in lines[i]) { + for (int i = 0; i < lines.Count; i++) + { + foreach (FlexUtil.FlexItemCalculationInfo info in lines[i]) + { // TODO DEVSIX-5002 margin: auto is not supported // If a flex item has align-self: stretch, its computed cross size property is auto, // and neither of its cross-axis margins are auto, @@ -804,176 +934,215 @@ internal static void DetermineUsedCrossSizeOfEachFlexItem(IList(Property.MIN_HEIGHT) != null ? minHeight : null; } private static void ApplyAlignItemsAndAlignSelf(IList> lines, FlexContainerRenderer - renderer, IList lineCrossSizes) { + renderer, IList lineCrossSizes) + { bool isColumnDirection = IsColumnDirection(renderer); AlignmentPropertyValue itemsAlignment = (AlignmentPropertyValue)renderer.GetProperty(Property.ALIGN_ITEMS, AlignmentPropertyValue.STRETCH); System.Diagnostics.Debug.Assert(lines.Count == lineCrossSizes.Count); // Line order becomes important for counting nextLineShift - if (renderer.IsWrapReverse()) { + if (renderer.IsWrapReverse()) + { JavaCollectionsUtil.Reverse(lines); JavaCollectionsUtil.Reverse(lineCrossSizes); } float lineShift; float nextLineShift = 0; - for (int i = 0; i < lines.Count; ++i) { + for (int i = 0; i < lines.Count; ++i) + { lineShift = nextLineShift; IList line = lines[i]; float lineCrossSize = lineCrossSizes[i]; // Used to calculate an extra space between the right/bottom point of the current line and left/top point // of the next line nextLineShift = lineCrossSize - line[0].GetOuterCrossSize(line[0].crossSize); - foreach (FlexUtil.FlexItemCalculationInfo itemInfo in line) { - if (isColumnDirection) { + foreach (FlexUtil.FlexItemCalculationInfo itemInfo in line) + { + if (isColumnDirection) + { itemInfo.xShift = lineShift; } - else { + else + { itemInfo.yShift = lineShift; } AlignmentPropertyValue selfAlignment = (AlignmentPropertyValue)itemInfo.renderer.GetProperty(Property.ALIGN_SELF, itemsAlignment); float freeSpace = lineCrossSize - itemInfo.GetOuterCrossSize(itemInfo.crossSize); nextLineShift = Math.Min(nextLineShift, freeSpace); - switch (selfAlignment) { + switch (selfAlignment) + { case AlignmentPropertyValue.SELF_END: - case AlignmentPropertyValue.END: { - if (isColumnDirection) { - itemInfo.xShift += freeSpace; - } - else { - itemInfo.yShift += freeSpace; - } - nextLineShift = 0; - break; - } - - case AlignmentPropertyValue.FLEX_END: { - if (!renderer.IsWrapReverse()) { - if (isColumnDirection) { + case AlignmentPropertyValue.END: + { + if (isColumnDirection) + { itemInfo.xShift += freeSpace; } - else { + else + { itemInfo.yShift += freeSpace; } nextLineShift = 0; + break; } - break; - } - case AlignmentPropertyValue.CENTER: { - if (isColumnDirection) { - itemInfo.xShift += freeSpace / 2; - } - else { - itemInfo.yShift += freeSpace / 2; + case AlignmentPropertyValue.FLEX_END: + { + if (!renderer.IsWrapReverse()) + { + if (isColumnDirection) + { + itemInfo.xShift += freeSpace; + } + else + { + itemInfo.yShift += freeSpace; + } + nextLineShift = 0; + } + break; } - nextLineShift = Math.Min(nextLineShift, freeSpace / 2); - break; - } - case AlignmentPropertyValue.FLEX_START: { - if (renderer.IsWrapReverse()) { - if (isColumnDirection) { - itemInfo.xShift += freeSpace; + case AlignmentPropertyValue.CENTER: + { + if (isColumnDirection) + { + itemInfo.xShift += freeSpace / 2; } - else { - itemInfo.yShift += freeSpace; + else + { + itemInfo.yShift += freeSpace / 2; } - nextLineShift = 0; + nextLineShift = Math.Min(nextLineShift, freeSpace / 2); + break; + } + + case AlignmentPropertyValue.FLEX_START: + { + if (renderer.IsWrapReverse()) + { + if (isColumnDirection) + { + itemInfo.xShift += freeSpace; + } + else + { + itemInfo.yShift += freeSpace; + } + nextLineShift = 0; + } + break; } - break; - } case AlignmentPropertyValue.START: case AlignmentPropertyValue.BASELINE: case AlignmentPropertyValue.SELF_START: case AlignmentPropertyValue.STRETCH: case AlignmentPropertyValue.NORMAL: - default: { - break; - } + default: + { + break; + } } } } // We don't need to do anything in these cases // Reverse back - if (renderer.IsWrapReverse()) { + if (renderer.IsWrapReverse()) + { JavaCollectionsUtil.Reverse(lines); JavaCollectionsUtil.Reverse(lineCrossSizes); } } private static void ApplyJustifyContent(IList> lines, FlexContainerRenderer - renderer, float mainSize, float containerMainSize) { + renderer, float mainSize, float containerMainSize) + { JustifyContent justifyContent = (JustifyContent)renderer.GetProperty(Property.JUSTIFY_CONTENT , JustifyContent.FLEX_START); bool containsFixedHeight = containerMainSize > 0; bool isFixedHeightAppliedOnTheCurrentPage = containsFixedHeight && containerMainSize < mainSize; - if (renderer.IsWrapReverse()) { + if (renderer.IsWrapReverse()) + { JavaCollectionsUtil.Reverse(lines); } - foreach (IList line in lines) { + foreach (IList line in lines) + { float childrenMainSize = 0; // Items order becomes important for justification bool isColumnReverse = FlexDirectionPropertyValue.COLUMN_REVERSE == renderer.GetProperty(Property.FLEX_DIRECTION, null); - if (isColumnReverse) { + if (isColumnReverse) + { JavaCollectionsUtil.Reverse(line); } IList lineToJustify = new List(); - for (int i = 0; i < line.Count; ++i) { + for (int i = 0; i < line.Count; ++i) + { FlexUtil.FlexItemCalculationInfo itemInfo = line[i]; - if (i != 0 && IsColumnDirection(renderer) && !isFixedHeightAppliedOnTheCurrentPage && lines.Count == 1 && - childrenMainSize + itemInfo.GetOuterMainSize(itemInfo.mainSize) > mainSize + EPSILON) { + if (i != 0 && IsColumnDirection(renderer) && !isFixedHeightAppliedOnTheCurrentPage && lines.Count == 1 && + childrenMainSize + itemInfo.GetOuterMainSize(itemInfo.mainSize) > mainSize + EPSILON) + { break; } childrenMainSize += itemInfo.GetOuterMainSize(itemInfo.mainSize); lineToJustify.Add(itemInfo); } // Reverse back - if (isColumnReverse) { + if (isColumnReverse) + { JavaCollectionsUtil.Reverse(line); JavaCollectionsUtil.Reverse(lineToJustify); } float freeSpace = 0; - if (!IsColumnDirection(renderer)) { + if (!IsColumnDirection(renderer)) + { freeSpace = mainSize - childrenMainSize; } - else { - if (containsFixedHeight) { + else + { + if (containsFixedHeight) + { // In case of column direction we should align only if container contains fixed height freeSpace = isFixedHeightAppliedOnTheCurrentPage ? containerMainSize - childrenMainSize : Math.Max(0, mainSize - childrenMainSize); @@ -981,64 +1150,79 @@ private static void ApplyJustifyContent(IList line, float initialFreeSpace - ) { + ) + { float result = initialFreeSpace; - foreach (FlexUtil.FlexItemCalculationInfo info in line) { - if (info.isFrozen) { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { + if (info.isFrozen) + { result -= info.GetOuterMainSize(info.mainSize); } - else { + else + { result -= info.GetOuterMainSize(info.flexBaseSize); } } return result; } - private static bool HasFlexibleItems(IList line) { - foreach (FlexUtil.FlexItemCalculationInfo info in line) { - if (!info.isFrozen) { + private static bool HasFlexibleItems(IList line) + { + foreach (FlexUtil.FlexItemCalculationInfo info in line) + { + if (!info.isFrozen) + { return true; } } return false; } -//\cond DO_NOT_DOCUMENT - internal static bool IsZero(float value) { + //\cond DO_NOT_DOCUMENT + internal static bool IsZero(float value) + { return Math.Abs(value) < EPSILON; } -//\endcond + //\endcond private static IList CreateFlexItemCalculationInfos(FlexContainerRenderer - flexContainerRenderer, float flexContainerMainSize, float crossSize) { + flexContainerRenderer, float flexContainerMainSize, float crossSize) + { IList childRenderers = flexContainerRenderer.GetChildRenderers(); IList flexItems = new List(); - foreach (IRenderer renderer in childRenderers) { - if (renderer is AbstractRenderer) { + foreach (IRenderer renderer in childRenderers) + { + if (renderer is AbstractRenderer) + { AbstractRenderer abstractRenderer = (AbstractRenderer)renderer; // TODO DEVSIX-5091 improve determining of the flex base size when flex-basis: content float maxMainSize = CalculateMaxMainSize(abstractRenderer, flexContainerMainSize, IsColumnDirection(flexContainerRenderer ), crossSize); float flexBasis; bool flexBasisContent = false; - if (renderer.GetProperty(Property.FLEX_BASIS) == null) { + if (renderer.GetProperty(Property.FLEX_BASIS) == null) + { flexBasis = maxMainSize; flexBasisContent = true; } - else { + else + { // For column layout layoutBox height should not be taken into account while calculating flexBasis // in percents. If flex container doesn't have a definite size, flex basis percents should not be // taken into account. - float containerMainSize = IsColumnDirection(flexContainerRenderer) ? GetMainSize(flexContainerRenderer, new + float containerMainSize = IsColumnDirection(flexContainerRenderer) ? GetMainSize(flexContainerRenderer, new Rectangle(0, 0)) : flexContainerMainSize; flexBasis = (float)abstractRenderer.RetrieveUnitValue(containerMainSize, Property.FLEX_BASIS); - if (AbstractRenderer.IsBorderBoxSizing(abstractRenderer)) { + if (AbstractRenderer.IsBorderBoxSizing(abstractRenderer)) + { flexBasis -= AbstractRenderer.CalculatePaddingBorderWidth(abstractRenderer); } } @@ -1050,58 +1234,84 @@ internal static bool IsZero(float value) { ), crossSize); flexItems.Add(flexItemInfo); } + else if (renderer is AreaBreakRenderer) + { + var divWithPageBreak = new Element.Div(); + divWithPageBreak.SetProperty(Property.AREA_BREAK_TYPE, AreaBreakType.NEXT_PAGE); + AbstractRenderer divRendererWithPageBreak = new DivRenderer(divWithPageBreak); + + FlexUtil.FlexItemCalculationInfo flexItemInfo = new FlexUtil.FlexItemCalculationInfo(divRendererWithPageBreak + , 1, 1, 1, flexContainerMainSize, true, IsColumnDirection(flexContainerRenderer + ), crossSize); + flexItems.Add(flexItemInfo); + } } return flexItems; } - private static float CalculateMaxMainSize(AbstractRenderer flexItemRenderer, float flexContainerMainSize, - bool isColumnDirection, float crossSize) { + private static float CalculateMaxMainSize(AbstractRenderer flexItemRenderer, float flexContainerMainSize, + bool isColumnDirection, float crossSize) + { float? maxMainSize; - if (flexItemRenderer is TableRenderer) { + if (flexItemRenderer is TableRenderer) + { // TODO DEVSIX-5214 we can't call TableRenderer#retrieveWidth method as far as it can throw NPE - if (isColumnDirection) { + if (isColumnDirection) + { float? itemRendererMaxHeight = flexItemRenderer.RetrieveMaxHeight(); maxMainSize = itemRendererMaxHeight; - if (maxMainSize == null) { + if (maxMainSize == null) + { maxMainSize = CalculateHeight(flexItemRenderer, crossSize); } } - else { + else + { maxMainSize = flexItemRenderer.GetMinMaxWidth().GetMaxWidth(); } - if (isColumnDirection) { + if (isColumnDirection) + { maxMainSize = flexItemRenderer.ApplyMarginsBordersPaddings(new Rectangle(0, (float)maxMainSize), false).GetHeight (); } - else { + else + { maxMainSize = flexItemRenderer.ApplyMarginsBordersPaddings(new Rectangle((float)maxMainSize, 0), false).GetWidth (); } } - else { + else + { // We need to retrieve width and max-width manually because this methods take into account box-sizing maxMainSize = isColumnDirection ? flexItemRenderer.RetrieveHeight() : flexItemRenderer.RetrieveWidth(flexContainerMainSize ); - if (maxMainSize == null) { + if (maxMainSize == null) + { maxMainSize = isColumnDirection ? RetrieveMaxHeightForMainDirection(flexItemRenderer) : flexItemRenderer.RetrieveMaxWidth (flexContainerMainSize); } - if (maxMainSize == null) { - if (flexItemRenderer is ImageRenderer) { + if (maxMainSize == null) + { + if (flexItemRenderer is ImageRenderer) + { // TODO DEVSIX-5269 getMinMaxWidth doesn't always return the original image width maxMainSize = isColumnDirection ? ((ImageRenderer)flexItemRenderer).GetImageHeight() : ((ImageRenderer)flexItemRenderer ).GetImageWidth(); } - else { - if (isColumnDirection) { + else + { + if (isColumnDirection) + { float? height = RetrieveMaxHeightForMainDirection(flexItemRenderer); - if (height == null) { + if (height == null) + { height = CalculateHeight(flexItemRenderer, crossSize); } maxMainSize = flexItemRenderer.ApplyMarginsBordersPaddings(new Rectangle(0, (float)height), false).GetHeight (); } - else { + else + { maxMainSize = flexItemRenderer.ApplyMarginsBordersPaddings(new Rectangle(flexItemRenderer.GetMinMaxWidth() .GetMaxWidth(), 0), false).GetWidth(); } @@ -1111,22 +1321,27 @@ private static float CalculateMaxMainSize(AbstractRenderer flexItemRenderer, flo return (float)maxMainSize; } - private static IList RetrieveCurrentPageLineCrossSizes(FlexContainerRenderer flexContainerRenderer, + private static IList RetrieveCurrentPageLineCrossSizes(FlexContainerRenderer flexContainerRenderer, IList> lines, IList lineCrossSizes, float? crossSize, Rectangle - layoutBox) { + layoutBox) + { float mainSize = GetMainSize(flexContainerRenderer, new Rectangle(0, 0)); - bool isColumnDirectionWithPagination = IsColumnDirection(flexContainerRenderer) && (mainSize < EPSILON || + bool isColumnDirectionWithPagination = IsColumnDirection(flexContainerRenderer) && (mainSize < EPSILON || mainSize > layoutBox.GetHeight() + EPSILON); - if (!isColumnDirectionWithPagination || crossSize == null) { + if (!isColumnDirectionWithPagination || crossSize == null) + { return lineCrossSizes; } IList currentPageLineCrossSizes = new List(); float flexLinesCrossSizesSum = 0; - for (int i = 0; i < lineCrossSizes.Count; ++i) { + for (int i = 0; i < lineCrossSizes.Count; ++i) + { float size = lineCrossSizes[i]; - if (flexLinesCrossSizesSum + size > crossSize + EPSILON || lines[i][0].mainSize > layoutBox.GetHeight() + - EPSILON) { - if (i == 0) { + if (flexLinesCrossSizesSum + size > crossSize + EPSILON || lines[i][0].mainSize > layoutBox.GetHeight() + + EPSILON) + { + if (i == 0) + { // We should add first line anyway currentPageLineCrossSizes.Add(size); } @@ -1138,102 +1353,107 @@ private static IList RetrieveCurrentPageLineCrossSizes(FlexContainerRende return currentPageLineCrossSizes; } - private static float CalculateHeight(AbstractRenderer flexItemRenderer, float width) { + private static float CalculateHeight(AbstractRenderer flexItemRenderer, float width) + { LayoutResult result = flexItemRenderer.Layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, AbstractRenderer .INF)))); return result.GetStatus() == LayoutResult.NOTHING ? 0 : result.GetOccupiedArea().GetBBox().GetHeight(); } -//\cond DO_NOT_DOCUMENT - internal class FlexItemCalculationInfo { -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT + internal class FlexItemCalculationInfo + { + //\cond DO_NOT_DOCUMENT internal AbstractRenderer renderer; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float flexBasis; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float flexShrink; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float flexGrow; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float minContent; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float maxContent; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float mainSize; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float crossSize; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float xShift; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float yShift; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT // Calculation-related fields internal float scaledFlexShrinkFactor; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal bool isFrozen = false; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal bool isMinViolated = false; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal bool isMaxViolated = false; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float flexBaseSize; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float hypotheticalMainSize; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal float hypotheticalCrossSize; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal bool flexBasisContent; -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT + //\cond DO_NOT_DOCUMENT internal bool isColumnDirection; -//\endcond + //\endcond public FlexItemCalculationInfo(AbstractRenderer renderer, float flexBasis, float flexGrow, float flexShrink - , float areaMainSize, bool flexBasisContent, bool isColumnDirection, float crossSize) { + , float areaMainSize, bool flexBasisContent, bool isColumnDirection, float crossSize) + { this.isColumnDirection = isColumnDirection; this.flexBasisContent = flexBasisContent; this.renderer = renderer; this.flexBasis = flexBasis; - if (flexShrink < 0) { + if (flexShrink < 0) + { throw new ArgumentException(LayoutExceptionMessageConstant.FLEX_SHRINK_CANNOT_BE_NEGATIVE); } this.flexShrink = flexShrink; - if (flexGrow < 0) { + if (flexGrow < 0) + { throw new ArgumentException(LayoutExceptionMessageConstant.FLEX_GROW_CANNOT_BE_NEGATIVE); } this.flexGrow = flexGrow; @@ -1247,62 +1467,74 @@ public FlexItemCalculationInfo(AbstractRenderer renderer, float flexBasis, float this.maxContent = maxMainSize == null ? AbstractRenderer.INF : (float)maxMainSize; } - public virtual Rectangle ToRectangle() { + public virtual Rectangle ToRectangle() + { return isColumnDirection ? new Rectangle(xShift, yShift, GetOuterCrossSize(crossSize), GetOuterMainSize(mainSize )) : new Rectangle(xShift, yShift, GetOuterMainSize(mainSize), GetOuterCrossSize(crossSize)); } -//\cond DO_NOT_DOCUMENT - internal virtual float GetOuterMainSize(float size) { - return isColumnDirection ? renderer.ApplyMarginsBordersPaddings(new Rectangle(0, size), true).GetHeight() : + //\cond DO_NOT_DOCUMENT + internal virtual float GetOuterMainSize(float size) + { + return isColumnDirection ? renderer.ApplyMarginsBordersPaddings(new Rectangle(0, size), true).GetHeight() : renderer.ApplyMarginsBordersPaddings(new Rectangle(size, 0), true).GetWidth(); } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT - internal virtual float GetInnerMainSize(float size) { + //\cond DO_NOT_DOCUMENT + internal virtual float GetInnerMainSize(float size) + { return isColumnDirection ? renderer.ApplyMarginsBordersPaddings(new Rectangle(0, size), false).GetHeight() : renderer.ApplyMarginsBordersPaddings(new Rectangle(size, 0), false).GetWidth(); } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT - internal virtual float GetOuterCrossSize(float size) { - return isColumnDirection ? renderer.ApplyMarginsBordersPaddings(new Rectangle(size, 0), true).GetWidth() : + //\cond DO_NOT_DOCUMENT + internal virtual float GetOuterCrossSize(float size) + { + return isColumnDirection ? renderer.ApplyMarginsBordersPaddings(new Rectangle(size, 0), true).GetWidth() : renderer.ApplyMarginsBordersPaddings(new Rectangle(0, size), true).GetHeight(); } -//\endcond + //\endcond -//\cond DO_NOT_DOCUMENT - internal virtual float GetInnerCrossSize(float size) { - return isColumnDirection ? renderer.ApplyMarginsBordersPaddings(new Rectangle(size, 0), false).GetWidth() : + //\cond DO_NOT_DOCUMENT + internal virtual float GetInnerCrossSize(float size) + { + return isColumnDirection ? renderer.ApplyMarginsBordersPaddings(new Rectangle(size, 0), false).GetWidth() : renderer.ApplyMarginsBordersPaddings(new Rectangle(0, size), false).GetHeight(); } -//\endcond + //\endcond - private float CalculateMinContentAuto(float flexContainerMainSize, float crossSize) { + private float CalculateMinContentAuto(float flexContainerMainSize, float crossSize) + { // Automatic Minimum Size of Flex Items https://www.w3.org/TR/css-flexbox-1/#content-based-minimum-size float? specifiedSizeSuggestion = CalculateSpecifiedSizeSuggestion(flexContainerMainSize); float contentSizeSuggestion = CalculateContentSizeSuggestion(flexContainerMainSize, crossSize); - if (renderer.HasAspectRatio() && specifiedSizeSuggestion == null) { + if (renderer.HasAspectRatio() && specifiedSizeSuggestion == null) + { // However, if the box has an aspect ratio and no specified size, // its content-based minimum size is the smaller of its content size suggestion // and its transferred size suggestion float? transferredSizeSuggestion = CalculateTransferredSizeSuggestion(flexContainerMainSize); - if (transferredSizeSuggestion == null) { + if (transferredSizeSuggestion == null) + { return contentSizeSuggestion; } - else { + else + { return Math.Min(contentSizeSuggestion, (float)transferredSizeSuggestion); } } - else { - if (specifiedSizeSuggestion == null) { + else + { + if (specifiedSizeSuggestion == null) + { // If the box has neither a specified size suggestion nor an aspect ratio, // its content-based minimum size is the content size suggestion. return contentSizeSuggestion; } - else { + else + { // In general, the content-based minimum size of a flex item is the smaller // of its content size suggestion and its specified size suggestion return Math.Min(contentSizeSuggestion, (float)specifiedSizeSuggestion); @@ -1321,11 +1553,13 @@ private float CalculateMinContentAuto(float flexContainerMainSize, float crossSi /// if they are definite), converted through the aspect ratio. It is otherwise undefined. /// /// transferred size suggestion if it can be calculated, null otherwise - private float? CalculateTransferredSizeSuggestion(float flexContainerMainSize) { + private float? CalculateTransferredSizeSuggestion(float flexContainerMainSize) + { float? transferredSizeSuggestion = null; float? crossSize = isColumnDirection ? renderer.RetrieveWidth(flexContainerMainSize) : renderer.RetrieveHeight (); - if (renderer.HasAspectRatio() && crossSize != null) { + if (renderer.HasAspectRatio() && crossSize != null) + { transferredSizeSuggestion = crossSize * renderer.GetAspectRatio(); transferredSizeSuggestion = ClampValueByCrossSizesConvertedThroughAspectRatio((float)transferredSizeSuggestion , flexContainerMainSize); @@ -1344,15 +1578,20 @@ private float CalculateMinContentAuto(float flexContainerMainSize, float crossSi /// /// the width of the flex container /// specified size suggestion if it's definite, null otherwise - private float? CalculateSpecifiedSizeSuggestion(float flexContainerMainSize) { + private float? CalculateSpecifiedSizeSuggestion(float flexContainerMainSize) + { float? mainSizeSuggestion = null; - if (isColumnDirection) { - if (renderer.HasProperty(Property.HEIGHT)) { + if (isColumnDirection) + { + if (renderer.HasProperty(Property.HEIGHT)) + { mainSizeSuggestion = renderer.RetrieveHeight(); } } - else { - if (renderer.HasProperty(Property.WIDTH)) { + else + { + if (renderer.HasProperty(Property.WIDTH)) + { mainSizeSuggestion = renderer.RetrieveWidth(flexContainerMainSize); } } @@ -1366,52 +1605,61 @@ private float CalculateMinContentAuto(float flexContainerMainSize, float crossSi /// /// the width of the flex container /// content size suggestion - private float CalculateContentSizeSuggestion(float flexContainerMainSize, float crossSize) { + private float CalculateContentSizeSuggestion(float flexContainerMainSize, float crossSize) + { UnitValue rendererWidth = renderer.ReplaceOwnProperty(Property.WIDTH, null); UnitValue rendererHeight = renderer.ReplaceOwnProperty(Property.HEIGHT, null); float minContentSize; - if (isColumnDirection) { + if (isColumnDirection) + { float? height = RetrieveMinHeightForMainDirection(renderer); - if (height == null) { + if (height == null) + { height = CalculateHeight(renderer, crossSize); } minContentSize = GetInnerMainSize((float)height); } - else { + else + { MinMaxWidth minMaxWidth = renderer.GetMinMaxWidth(); minContentSize = GetInnerMainSize(minMaxWidth.GetMinWidth()); } renderer.ReturnBackOwnProperty(Property.HEIGHT, rendererHeight); renderer.ReturnBackOwnProperty(Property.WIDTH, rendererWidth); - if (renderer.HasAspectRatio()) { + if (renderer.HasAspectRatio()) + { minContentSize = ClampValueByCrossSizesConvertedThroughAspectRatio(minContentSize, flexContainerMainSize); } float? maxMainSize = isColumnDirection ? RetrieveMaxHeightForMainDirection(renderer) : renderer.RetrieveMaxWidth (flexContainerMainSize); - if (maxMainSize == null) { + if (maxMainSize == null) + { maxMainSize = AbstractRenderer.INF; } return Math.Min(minContentSize, (float)maxMainSize); } - private float ClampValueByCrossSizesConvertedThroughAspectRatio(float value, float flexContainerMainSize) { + private float ClampValueByCrossSizesConvertedThroughAspectRatio(float value, float flexContainerMainSize) + { float? maxCrossSize = isColumnDirection ? renderer.RetrieveMaxWidth(flexContainerMainSize) : renderer.RetrieveMaxHeight (); if (maxCrossSize == null || !renderer.HasProperty(isColumnDirection ? Property.MAX_WIDTH : Property.MAX_HEIGHT - )) { + )) + { maxCrossSize = AbstractRenderer.INF; } float? minCrossSize = isColumnDirection ? renderer.RetrieveMinWidth(flexContainerMainSize) : renderer.RetrieveMinHeight (); if (minCrossSize == null || !renderer.HasProperty(isColumnDirection ? Property.MIN_WIDTH : Property.MIN_HEIGHT - )) { + )) + { minCrossSize = 0F; } return Math.Min(Math.Max((float)(minCrossSize * renderer.GetAspectRatio()), value), (float)(maxCrossSize * renderer.GetAspectRatio())); } } -//\endcond + //\endcond } -//\endcond + //\endcond }