/// <summary>This method use derivative of function defined on interval: [xMin, xMax] to find its local minimum and maximum.
        ///     </summary>
        /// <remarks>
        /// This method use derivative of function defined on interval: [xMin, xMax] to find its local minimum and maximum.
        /// It also calculate other handy values needed for the creation of
        /// <see cref="RotationMinMaxWidth"/>.
        /// </remarks>
        /// <param name="func">
        /// the
        /// <see cref="WidthFunction.GetRotatedWidth(double)"/>
        /// of this instance is used as analysed function
        /// </param>
        /// <param name="xMin">the smallest possible value of function argument</param>
        /// <param name="xMax">the biggest possible value of function argument</param>
        /// <returns>
        /// the calculated
        /// <see cref="RotationMinMaxWidth"/>
        /// </returns>
        private static iText.Layout.Minmaxwidth.RotationMinMaxWidth Calculate(RotationMinMaxWidth.WidthFunction func
                                                                              , double xMin, double xMax)
        {
            double minWidthOrigin;
            double maxWidthOrigin;
            //Derivative sign change point
            double x0 = func.GetWidthDerivativeZeroPoint();

            //The point x0 may be in three different positions in relation to function interval.
            if (x0 < xMin)
            {
                //The function is decreasing in this case on whole interval so the local mim and max are on interval borders
                minWidthOrigin = xMin;
                maxWidthOrigin = xMax;
            }
            else
            {
                if (x0 > xMax)
                {
                    //The function is increasing in this case on whole interval so the local mim and max are on interval borders
                    minWidthOrigin = xMax;
                    maxWidthOrigin = xMin;
                }
                else
                {
                    //The function derivative changes its sign from negative to positive on function interval in point x0,
                    //so its local min is x0, and its local maximum is on one of interval borders
                    minWidthOrigin = x0;
                    maxWidthOrigin = func.GetRotatedWidth(xMax) > func.GetRotatedWidth(xMin) ? xMax : xMin;
                }
            }
            return(new iText.Layout.Minmaxwidth.RotationMinMaxWidth(func.GetRotatedWidth(minWidthOrigin), func.GetRotatedWidth
                                                                        (maxWidthOrigin), minWidthOrigin, maxWidthOrigin, func.GetRotatedHeight(minWidthOrigin), func.GetRotatedHeight
                                                                        (maxWidthOrigin)));
        }
        /// <summary>
        /// Heuristic method, based on the assumption that area of element stays the same, when we try to
        /// layout it with different available width (available width is between min-width and max-width).
        /// </summary>
        /// <param name="angle">rotation angle in radians</param>
        /// <param name="area">the constant area</param>
        /// <param name="elementMinMaxWidth">NOT rotated element min-max-width</param>
        /// <param name="availableWidth">the maximum width of area the element will occupy after rotation.</param>
        /// <returns>possible min-max-width of element after rotation</returns>
        public static iText.Layout.Minmaxwidth.RotationMinMaxWidth Calculate(double angle, double area, MinMaxWidth
                                                                             elementMinMaxWidth, double availableWidth)
        {
            RotationMinMaxWidth.WidthFunction          function       = new RotationMinMaxWidth.WidthFunction(angle, area);
            RotationMinMaxWidth.WidthFunction.Interval validArguments = function.GetValidOriginalWidths(availableWidth
                                                                                                        );
            if (validArguments == null)
            {
                return(null);
            }
            double xMin = Math.Max(elementMinMaxWidth.GetMinWidth(), validArguments.GetMin());
            double xMax = Math.Min(elementMinMaxWidth.GetMaxWidth(), validArguments.GetMax());

            if (xMax < xMin)
            {
                //Initially the null was returned in this case, but this result in old layout logic that looks worse in most cases.
                //The difference between min and max is not that big and not critical.
                double rotatedWidth  = function.GetRotatedWidth(xMin);
                double rotatedHeight = function.GetRotatedHeight(xMin);
                return(new iText.Layout.Minmaxwidth.RotationMinMaxWidth(rotatedWidth, rotatedWidth, xMin, xMin, rotatedHeight
                                                                        , rotatedHeight));
            }
            return(Calculate(function, xMin, xMax));
        }
 /// <summary>
 /// Heuristic method, based on the assumption that area of element stays the same, when we try to
 /// layout it with different available width (available width is between min-width and max-width).
 /// </summary>
 /// <param name="angle">rotation angle in radians</param>
 /// <param name="area">the constant area</param>
 /// <param name="elementMinMaxWidth">NOT rotated element min-max-width</param>
 /// <returns>possible min-max-width of element after rotation</returns>
 public static iText.Layout.Minmaxwidth.RotationMinMaxWidth Calculate(double angle, double area, MinMaxWidth
                                                                      elementMinMaxWidth)
 {
     RotationMinMaxWidth.WidthFunction function = new RotationMinMaxWidth.WidthFunction(angle, area);
     return(Calculate(function, elementMinMaxWidth.GetMinWidth(), elementMinMaxWidth.GetMaxWidth()));
 }