/// <summary>Set the calculated dimension to the manually set dimension in the passed float array</summary> /// <param name="dim">Dimension Container containing the manually set dimension</param> /// <param name="dimensions">array of calculated auto values for boxes in the given dimension</param> /// <param name="index">position in the array to replace</param> private void SetManualDimension(DimensionContainer dim, float[] dimensions, int index) { if (dim != null && !dim.IsAutoDimension()) { dimensions[index] = dim.dimension; } }
/// <summary>Check if a calculated dimension value needs to be recalculated</summary> /// <param name="dim">Dimension container containing min and max dimension info</param> /// <param name="dimensions">array of calculated auto values for boxes in the given dimension</param> /// <param name="index">position in the array to look at</param> /// <returns><c>true</c> if the values in dimensions trigger a recalculation, <c>false</c> otherwise</returns> private bool RecalculateIfNecessary(DimensionContainer dim, float[] dimensions, int index) { if (dim != null) { if (dimensions[index] < dim.minDimension && dim.IsAutoDimension()) { dim.dimension = dim.minDimension; return(true); } if (dimensions[index] > dim.maxDimension && dim.IsAutoDimension()) { dim.dimension = dim.maxDimension; return(true); } } return(false); }
/// <summary> /// See the algorithm detailed at https://www.w3.org/TR/css3-page/#margin-dimension /// Divide the available dimension along the A,B and C according to their properties. /// </summary> /// <param name="dimA">object containing the dimension-related properties of A</param> /// <param name="dimB">object containing the dimension-related properties of B</param> /// <param name="dimC">object containing the dimension-related properties of C</param> /// <param name="availableDimension">maximum available dimension that can be taken up</param> /// <returns>float[3] containing the distributed dimensions of A at [0], B at [1] and C at [2]</returns> private float[] CalculatePageMarginBoxDimensions(DimensionContainer dimA, DimensionContainer dimB, DimensionContainer dimC, float availableDimension) { float maxContentDimensionA = 0; float minContentDimensionA = 0; float maxContentDimensionB = 0; float minContentDimensionB = 0; float maxContentDimensionC = 0; float minContentDimensionC = 0; float[] dimensions = new float[3]; if (IsContainerEmpty(dimA) && IsContainerEmpty(dimB) && IsContainerEmpty(dimC)) { return(dimensions); } //Calculate widths //Check if B is present if (IsContainerEmpty(dimB)) { //Single box present if (IsContainerEmpty(dimA)) { if (dimC.IsAutoDimension()) { //Allocate everything to C dimensions[2] = availableDimension; } else { dimensions[2] = dimC.dimension; } } else { if (IsContainerEmpty(dimC)) { if (dimA.IsAutoDimension()) { //Allocate everything to A dimensions[0] = availableDimension; } else { dimensions[0] = dimA.dimension; } } else { if (dimA.IsAutoDimension() && dimC.IsAutoDimension()) { //Gather input maxContentDimensionA = dimA.maxContentDimension; minContentDimensionA = dimA.minContentDimension; maxContentDimensionC = dimC.maxContentDimension; minContentDimensionC = dimC.minContentDimension; float[] distributedWidths = DistributeDimensionBetweenTwoBoxes(maxContentDimensionA, minContentDimensionA, maxContentDimensionC, minContentDimensionC, availableDimension); dimensions = new float[] { distributedWidths[0], 0f, distributedWidths[1] }; } else { if (!dimA.IsAutoDimension()) { dimensions[0] = dimA.dimension; } else { dimensions[0] = availableDimension - dimC.dimension; } if (!dimC.IsAutoDimension()) { dimensions[2] = dimC.dimension; } else { dimensions[2] = availableDimension - dimA.dimension; } } } } } else { //Check for edge cases if (!IsContainerEmpty(dimA)) { if (dimA.IsAutoDimension()) { maxContentDimensionA = dimA.maxContentDimension; minContentDimensionA = dimA.minContentDimension; } else { maxContentDimensionA = dimA.dimension; minContentDimensionA = dimA.dimension; } } if (!IsContainerEmpty(dimC)) { if (dimC.IsAutoDimension()) { maxContentDimensionC = dimC.maxContentDimension; minContentDimensionC = dimC.minContentDimension; } else { maxContentDimensionC = dimC.dimension; minContentDimensionC = dimC.dimension; } } if (dimB.IsAutoDimension()) { //Construct box AC float maxContentWidthAC; float minContentWidthAC; maxContentWidthAC = 2 * Math.Max(maxContentDimensionA, maxContentDimensionC); minContentWidthAC = 2 * Math.Max(minContentDimensionA, minContentDimensionC); //Determine width box B maxContentDimensionB = dimB.maxContentDimension; minContentDimensionB = dimB.minContentDimension; float[] distributedDimensions = DistributeDimensionBetweenTwoBoxes(maxContentDimensionB, minContentDimensionB , maxContentWidthAC, minContentWidthAC, availableDimension); //Determine width boxes A & C float newAvailableDimension = (availableDimension - distributedDimensions[0]) / 2; dimensions = new float[] { newAvailableDimension, distributedDimensions[0], newAvailableDimension }; } else { dimensions[1] = dimB.dimension; float newAvailableDimension = (availableDimension - dimensions[1]) / 2; if (newAvailableDimension > float.MaxValue - MinMaxWidthUtils.GetEps()) { newAvailableDimension = float.MaxValue - MinMaxWidthUtils.GetEps(); } dimensions[0] = Math.Min(maxContentDimensionA, newAvailableDimension) + MinMaxWidthUtils.GetEps(); dimensions[2] = Math.Min(maxContentDimensionC, newAvailableDimension) + MinMaxWidthUtils.GetEps(); } SetManualDimension(dimA, dimensions, 0); SetManualDimension(dimC, dimensions, 2); } if (RecalculateIfNecessary(dimA, dimensions, 0) || RecalculateIfNecessary(dimB, dimensions, 1) || RecalculateIfNecessary (dimC, dimensions, 2)) { return(CalculatePageMarginBoxDimensions(dimA, dimB, dimC, availableDimension)); } RemoveNegativeValues(dimensions); return(dimensions); }
private bool IsContainerEmpty(DimensionContainer container) { return(container == null || Math.Abs(container.maxContentDimension) < EPSILON); }
private void DetermineSizes(int side) { float[][] marginsBordersPaddingsWidths = new float[][] { new float[4], new float[4], new float[4] }; for (int i = 0; i < 3; i++) { if (renderers[side * 4 + i + 1] != null) { marginsBordersPaddingsWidths[i][0] = GetSizeOfOneSide(renderers[side * 4 + i + 1], Property.MARGIN_TOP, Property .BORDER_TOP, Property.PADDING_TOP); marginsBordersPaddingsWidths[i][1] = GetSizeOfOneSide(renderers[side * 4 + i + 1], Property.MARGIN_RIGHT, Property.BORDER_RIGHT, Property.PADDING_RIGHT); marginsBordersPaddingsWidths[i][2] = GetSizeOfOneSide(renderers[side * 4 + i + 1], Property.MARGIN_BOTTOM, Property.BORDER_BOTTOM, Property.PADDING_BOTTOM); marginsBordersPaddingsWidths[i][3] = GetSizeOfOneSide(renderers[side * 4 + i + 1], Property.MARGIN_LEFT, Property .BORDER_LEFT, Property.PADDING_LEFT); } } Rectangle withoutMargins = pageSize.Clone().ApplyMargins(margins[0], margins[1], margins[2], margins[3], false ); IDictionary <String, PageMarginBoxContextNode> resolvedPMBMap = new Dictionary <String, PageMarginBoxContextNode >(); for (int i = side * 4 + 1; i < side * 4 + 4; i++) { if (nodes[i] != null) { resolvedPMBMap.Put(nodes[i].GetMarginBoxName(), nodes[i]); } } DimensionContainer[] dims = new DimensionContainer[3]; String[] cssRuleName = GetRuleNames(side); float withoutMarginsWidthOrHeight = side % 2 == 0 ? withoutMargins.GetWidth() : withoutMargins.GetHeight(); for (int i = 0; i < 3; i++) { if (side % 2 == 0) { dims[i] = RetrievePageMarginBoxWidths(resolvedPMBMap.Get(cssRuleName[i]), renderers[side * 4 + i + 1], withoutMarginsWidthOrHeight , marginsBordersPaddingsWidths[i][1] + marginsBordersPaddingsWidths[i][3]); } else { dims[i] = RetrievePageMarginBoxHeights(resolvedPMBMap.Get(cssRuleName[i]), renderers[side * 4 + i + 1], margins [side], withoutMarginsWidthOrHeight, marginsBordersPaddingsWidths[i][0] + marginsBordersPaddingsWidths [i][2]); } } float centerOrMiddleCoord; float[] widthOrHeightResults; widthOrHeightResults = CalculatePageMarginBoxDimensions(dims[0], dims[1], dims[2], withoutMarginsWidthOrHeight ); if (side % 2 == 0) { centerOrMiddleCoord = GetStartCoordForCenterOrMiddleBox(withoutMarginsWidthOrHeight, widthOrHeightResults[ 1], withoutMargins.GetLeft()); } else { centerOrMiddleCoord = GetStartCoordForCenterOrMiddleBox(withoutMarginsWidthOrHeight, widthOrHeightResults[ 1], withoutMargins.GetBottom()); } Rectangle[] result = GetRectangles(side, withoutMargins, centerOrMiddleCoord, widthOrHeightResults); for (int i = 0; i < 3; i++) { if (nodes[side * 4 + i + 1] != null) { nodes[side * 4 + i + 1].SetPageMarginBoxRectangle(new Rectangle(result[i]).IncreaseHeight(EPSILON)); UnitValue width = UnitValue.CreatePointValue(result[i].GetWidth() - marginsBordersPaddingsWidths[i][1] - marginsBordersPaddingsWidths [i][3]); UnitValue height = UnitValue.CreatePointValue(result[i].GetHeight() - marginsBordersPaddingsWidths[i][0] - marginsBordersPaddingsWidths[i][2]); if (Math.Abs(width.GetValue()) < EPSILON || Math.Abs(height.GetValue()) < EPSILON) { renderers[side * 4 + i + 1] = null; } else { renderers[side * 4 + i + 1].SetProperty(Property.WIDTH, width); renderers[side * 4 + i + 1].SetProperty(Property.HEIGHT, height); } } } }