public virtual void SplitAndOverflowInheritSpecialScriptsWordBreakPoints()
        {
            String       nonSpecialScriptText = "Some non-special script";
            TextRenderer textRenderer         = new TextRenderer(new Text(nonSpecialScriptText));

            textRenderer.SetProperty(Property.FONT, PdfFontFactory.CreateFont(REGULAR_FONT, PdfEncodings.IDENTITY_H));
            textRenderer.SetText(nonSpecialScriptText);
            NUnit.Framework.Assert.IsNull(textRenderer.GetSpecialScriptsWordBreakPoints());
            LineRenderer.IsTextRendererAndRequiresSpecialScriptPreLayoutProcessing(textRenderer);
            NUnit.Framework.Assert.IsNotNull(textRenderer.GetSpecialScriptsWordBreakPoints());
            NUnit.Framework.Assert.IsTrue(textRenderer.GetSpecialScriptsWordBreakPoints().IsEmpty());
            // layout is needed prior to calling #split() in order to fill TextRenderer fields required to be non-null
            PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new MemoryStream()));
            Document    document    = new Document(pdfDocument);

            textRenderer.SetParent(document.GetRenderer());
            LayoutArea layoutArea = new LayoutArea(1, new Rectangle(MinMaxWidthUtils.GetInfWidth(), AbstractRenderer.INF
                                                                    ));

            textRenderer.Layout(new LayoutContext(layoutArea));
            TextRenderer[] splitRenderers = textRenderer.Split(nonSpecialScriptText.Length / 2);
            foreach (TextRenderer split in splitRenderers)
            {
                NUnit.Framework.Assert.IsNotNull(split.GetSpecialScriptsWordBreakPoints());
                NUnit.Framework.Assert.IsTrue(split.GetSpecialScriptsWordBreakPoints().IsEmpty());
            }
        }
Beispiel #2
0
 private static float[] ToEffectiveTableColumnWidth(float[] tableColumnWidth)
 {
     float[] result = new float[tableColumnWidth.Length];
     for (int i = 0; i < result.Length; ++i)
     {
         result[i] = tableColumnWidth[i] + MinMaxWidthUtils.GetEps();
     }
     return(result);
 }
Beispiel #3
0
        public override MinMaxWidth GetMinMaxWidth()
        {
            LayoutResult errorResult = InitializeListSymbols(new LayoutContext(new LayoutArea(1, new Rectangle(MinMaxWidthUtils
                                                                                                               .GetInfWidth(), AbstractRenderer.INF))));

            if (errorResult != null)
            {
                return(MinMaxWidthUtils.CountDefaultMinMaxWidth(this));
            }
            return(base.GetMinMaxWidth());
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
 private static float ToEffectiveWidth(IBlockElement b, float fullWidth)
 {
     if (b is Table)
     {
         return(fullWidth + ((Table)b).GetNumberOfColumns() * MinMaxWidthUtils.GetEps());
     }
     else
     {
         return(fullWidth - MinMaxWidthUtils.GetBorderWidth(b) - MinMaxWidthUtils.GetMarginsWidth(b) - MinMaxWidthUtils
                .GetPaddingWidth(b) + MinMaxWidthUtils.GetEps());
     }
 }
Beispiel #6
0
        //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);
        }
        public virtual void NothingLayoutResult()
        {
            PdfDocument  pdfDocument  = new PdfDocument(new PdfWriter(new MemoryStream()));
            Document     document     = new Document(pdfDocument);
            TextRenderer textRenderer = new TextRenderer(new iText.Layout.Element.Text(THAI_TEXT));

            textRenderer.SetSpecialScriptsWordBreakPoints(new List <int>(JavaUtil.ArraysAsList(3, 8, 10, 12, 15, 20, 23
                                                                                               , 26, 28, 30, 36)));
            textRenderer.SetProperty(Property.FONT, PdfFontFactory.CreateFont(THAI_FONT, PdfEncodings.IDENTITY_H));
            LineRenderer lineRenderer = new LineRenderer();

            lineRenderer.SetParent(document.GetRenderer());
            lineRenderer.AddChild(textRenderer);
            LayoutArea layoutArea   = new LayoutArea(1, new Rectangle(MinMaxWidthUtils.GetInfWidth(), 10000));
            Rectangle  occupiedArea = lineRenderer.Layout(new LayoutContext(layoutArea)).GetOccupiedArea().GetBBox();
            LayoutArea decreasedHeightLayoutArea = new LayoutArea(1, new Rectangle(occupiedArea.GetWidth(), occupiedArea
                                                                                   .GetHeight() - 1));
            LayoutResult nothingExpected = lineRenderer.Layout(new LayoutContext(decreasedHeightLayoutArea));

            NUnit.Framework.Assert.AreEqual(LayoutResult.NOTHING, nothingExpected.GetStatus());
        }
 public override MinMaxWidth GetMinMaxWidth()
 {
     return(((MinMaxWidthLayoutResult)Layout(new LayoutContext(new LayoutArea(1, new Rectangle(MinMaxWidthUtils
                                                                                               .GetInfWidth(), AbstractRenderer.INF))))).GetMinMaxWidth());
 }
        public override MinMaxWidth GetMinMaxWidth()
        {
            MinMaxWidth minMaxWidth = new MinMaxWidth();
            float?      rotation    = this.GetPropertyAsFloat(Property.ROTATION_ANGLE);

            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)
                {
                    bool restoreRotation = HasOwnProperty(Property.ROTATION_ANGLE);
                    SetProperty(Property.ROTATION_ANGLE, null);
                    MinMaxWidthLayoutResult result = (MinMaxWidthLayoutResult)Layout(new LayoutContext(new LayoutArea(1, new Rectangle
                                                                                                                          (MinMaxWidthUtils.GetInfWidth(), AbstractRenderer.INF))));
                    if (restoreRotation)
                    {
                        SetProperty(Property.ROTATION_ANGLE, rotation);
                    }
                    else
                    {
                        DeleteOwnProperty(Property.ROTATION_ANGLE);
                    }
                    minMaxWidth = result.GetMinMaxWidth();
                }
                if (minWidth != null)
                {
                    minMaxWidth.SetChildrenMinWidth((float)minWidth);
                }
                if (maxWidth != null)
                {
                    minMaxWidth.SetChildrenMaxWidth((float)maxWidth);
                }
                if (minMaxWidth.GetChildrenMinWidth() > minMaxWidth.GetChildrenMaxWidth())
                {
                    minMaxWidth.SetChildrenMaxWidth(minMaxWidth.GetChildrenMaxWidth());
                }
            }
            else
            {
                minMaxWidth.SetAdditionalWidth(CalculateAdditionalWidth(this));
            }
            return(rotation != null?RotationUtils.CountRotationMinMaxWidth(minMaxWidth, this) : minMaxWidth);
        }
Beispiel #10
0
        /// <summary>This method tries to calculate width of not rotated renderer, so after rotation it fits availableWidth.
        ///     </summary>
        /// <remarks>
        /// This method tries to calculate width of not rotated renderer, so after rotation it fits availableWidth.
        /// This method uses heuristics of
        /// <see cref="iText.Layout.Minmaxwidth.RotationMinMaxWidth.Calculate(double, double, iText.Layout.Minmaxwidth.MinMaxWidth, double)
        ///     "/>.
        /// It doesn't take into account any of height properties of renderer or height of layoutArea.
        /// The minMaxWidth calculations and initial layout may take long time, but they won't be called if the renderer have width property.
        /// </remarks>
        /// <param name="availableWidth">the width of layoutArea</param>
        /// <param name="renderer">the actual renderer</param>
        /// <returns>
        /// the width that should be set as width of layout area to properly layout element, or fallback to
        /// <see cref="AbstractRenderer.RetrieveWidth(float)"/>
        /// in case it can not be calculated, or renderer isn't rotated.
        /// </returns>
        public static float?RetrieveRotatedLayoutWidth(float availableWidth, AbstractRenderer renderer)
        {
            RotationUtils.PropertiesBackup backup = new RotationUtils.PropertiesBackup(renderer);
            float?rotation = backup.StoreFloatProperty(Property.ROTATION_ANGLE);

            if (rotation != null && renderer.GetProperty <UnitValue>(Property.WIDTH) == null)
            {
                float angle = (float)rotation;
                backup.StoreProperty <UnitValue>(Property.HEIGHT);
                backup.StoreProperty <UnitValue>(Property.MIN_HEIGHT);
                backup.StoreProperty <UnitValue>(Property.MAX_HEIGHT);
                MinMaxWidth minMaxWidth = renderer.GetMinMaxWidth();
                //Using this width for initial layout helps in case of small elements. They may have more free spaces but it's more likely they fit.
                float        length       = (minMaxWidth.GetMaxWidth() + minMaxWidth.GetMinWidth()) / 2 + MinMaxWidthUtils.GetEps();
                LayoutResult layoutResult = renderer.Layout(new LayoutContext(new LayoutArea(1, new Rectangle(length, AbstractRenderer
                                                                                                              .INF))));
                backup.RestoreProperty(Property.HEIGHT);
                backup.RestoreProperty(Property.MIN_HEIGHT);
                backup.RestoreProperty(Property.MAX_HEIGHT);
                Rectangle additions = new Rectangle(0, 0);
                renderer.ApplyPaddings(additions, true);
                renderer.ApplyBorderBox(additions, true);
                renderer.ApplyMargins(additions, true);
                if (layoutResult.GetOccupiedArea() != null)
                {
                    double area = layoutResult.GetOccupiedArea().GetBBox().GetWidth() * layoutResult.GetOccupiedArea().GetBBox
                                      ().GetHeight();
                    RotationMinMaxWidth result = RotationMinMaxWidth.Calculate(angle, area, minMaxWidth, availableWidth);
                    if (result != null)
                    {
                        backup.RestoreProperty(Property.ROTATION_ANGLE);
                        if (result.GetMaxWidthHeight() > result.GetMinWidthHeight())
                        {
                            return((float)(result.GetMinWidthOrigin() - additions.GetWidth() + MinMaxWidthUtils.GetEps()));
                        }
                        else
                        {
                            return((float)(result.GetMaxWidthOrigin() - additions.GetWidth() + MinMaxWidthUtils.GetEps()));
                        }
                    }
                }
            }
            backup.RestoreProperty(Property.ROTATION_ANGLE);
            return(renderer.RetrieveWidth(availableWidth));
        }
Beispiel #11
0
        /// <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);
        }