/// <summary> /// This method tries to calculate min-max-width of rotated element using heuristics /// of /// <see cref="iText.Layout.Minmaxwidth.RotationMinMaxWidth.Calculate(double, double, iText.Layout.Minmaxwidth.MinMaxWidth) /// "/>. /// </summary> /// <remarks> /// This method tries to calculate min-max-width of rotated element using heuristics /// of /// <see cref="iText.Layout.Minmaxwidth.RotationMinMaxWidth.Calculate(double, double, iText.Layout.Minmaxwidth.MinMaxWidth) /// "/>. /// This method may call /// <see cref="IRenderer.Layout(iText.Layout.Layout.LayoutContext)"/> /// once in best case /// (if the width is set on element, or if we are really lucky) and three times in worst case. /// </remarks> /// <param name="minMaxWidth">the minMaxWidth of NOT rotated renderer</param> /// <param name="renderer">the actual renderer</param> /// <returns>minMaxWidth of rotated renderer or original value in case rotated value can not be calculated, or renderer isn't rotated. /// </returns> public static MinMaxWidth CountRotationMinMaxWidth(MinMaxWidth minMaxWidth, AbstractRenderer renderer) { RotationUtils.PropertiesBackup backup = new RotationUtils.PropertiesBackup(renderer); float?rotation = backup.StoreFloatProperty(Property.ROTATION_ANGLE); if (rotation != null) { float angle = (float)rotation; //This width results in more accurate values for min-width calculations. float layoutWidth = minMaxWidth.GetMaxWidth() + MinMaxWidthUtils.GetEps(); LayoutResult layoutResult = renderer.Layout(new LayoutContext(new LayoutArea(1, new Rectangle(layoutWidth, AbstractRenderer.INF)))); if (layoutResult.GetOccupiedArea() != null) { Rectangle layoutBBox = layoutResult.GetOccupiedArea().GetBBox(); if (MinMaxWidthUtils.IsEqual(minMaxWidth.GetMinWidth(), minMaxWidth.GetMaxWidth())) { backup.RestoreProperty(Property.ROTATION_ANGLE); float rotatedWidth = (float)RotationMinMaxWidth.CalculateRotatedWidth(layoutBBox, angle); return(new MinMaxWidth(rotatedWidth, rotatedWidth, 0)); } double area = layoutResult.GetOccupiedArea().GetBBox().GetWidth() * layoutResult.GetOccupiedArea().GetBBox ().GetHeight(); RotationMinMaxWidth rotationMinMaxWidth = RotationMinMaxWidth.Calculate(angle, area, minMaxWidth); float?rotatedMinWidth = GetLayoutRotatedWidth(renderer, (float)rotationMinMaxWidth.GetMinWidthOrigin(), layoutBBox , angle); if (rotatedMinWidth != null) { if (rotatedMinWidth > rotationMinMaxWidth.GetMaxWidth()) { rotationMinMaxWidth.SetChildrenMinWidth((float)rotatedMinWidth); float?rotatedMaxWidth = GetLayoutRotatedWidth(renderer, (float)rotationMinMaxWidth.GetMaxWidthOrigin(), layoutBBox , angle); if (rotatedMaxWidth != null && rotatedMaxWidth > rotatedMinWidth) { rotationMinMaxWidth.SetChildrenMaxWidth((float)rotatedMaxWidth); } else { rotationMinMaxWidth.SetChildrenMaxWidth((float)rotatedMinWidth); } } else { rotationMinMaxWidth.SetChildrenMinWidth((float)rotatedMinWidth); } backup.RestoreProperty(Property.ROTATION_ANGLE); return(rotationMinMaxWidth); } } } backup.RestoreProperty(Property.ROTATION_ANGLE); return(minMaxWidth); }
//Get actual width of element based on it's layout. May use occupied are of layout result of initial layout for time saving. private static float?GetLayoutRotatedWidth(AbstractRenderer renderer, float availableWidth, Rectangle previousBBox , double angle) { if (MinMaxWidthUtils.IsEqual(availableWidth, previousBBox.GetWidth())) { return((float)RotationMinMaxWidth.CalculateRotatedWidth(previousBBox, angle)); } LayoutResult result = renderer.Layout(new LayoutContext(new LayoutArea(1, new Rectangle(availableWidth + MinMaxWidthUtils .GetEps(), AbstractRenderer.INF)))); if (result.GetOccupiedArea() != null) { return((float)RotationMinMaxWidth.CalculateRotatedWidth(result.GetOccupiedArea().GetBBox(), angle)); } return(null); }