示例#1
0
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            // Resolve width here in case it's relative, while parent width is still intact.
            // If it's inline-block context, relative width is already resolved.
            float?width = RetrieveWidth(layoutContext.GetArea().GetBBox().GetWidth());

            if (width != null)
            {
                UpdateWidth(UnitValue.CreatePointValue((float)width));
            }
            float      childrenMaxWidth = GetMinMaxWidth().GetMaxWidth();
            LayoutArea area             = layoutContext.GetArea().Clone();

            area.GetBBox().MoveDown(INF - area.GetBBox().GetHeight()).SetHeight(INF).SetWidth(childrenMaxWidth + EPS);
            LayoutResult layoutResult = base.Layout(new LayoutContext(area, layoutContext.GetMarginsCollapseInfo(), layoutContext
                                                                      .GetFloatRendererAreas(), layoutContext.IsClippedHeight()));

            if (layoutResult.GetStatus() != LayoutResult.FULL)
            {
                if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                {
                    layoutResult = MakeLayoutResultFull(layoutContext.GetArea(), layoutResult);
                }
                else
                {
                    return(new LayoutResult(LayoutResult.NOTHING, null, null, this, this));
                }
            }
            float     availableHeight = layoutContext.GetArea().GetBBox().GetHeight();
            bool      isClippedHeight = layoutContext.IsClippedHeight();
            Rectangle dummy           = new Rectangle(0, 0);

            ApplyMargins(dummy, true);
            ApplyBorderBox(dummy, true);
            ApplyPaddings(dummy, true);
            float additionalHeight = dummy.GetHeight();

            availableHeight -= additionalHeight;
            availableHeight  = Math.Max(availableHeight, 0);
            float actualHeight           = GetOccupiedArea().GetBBox().GetHeight() - additionalHeight;
            float finalSelectFieldHeight = GetFinalSelectFieldHeight(availableHeight, actualHeight, isClippedHeight);

            if (finalSelectFieldHeight < 0)
            {
                return(new LayoutResult(LayoutResult.NOTHING, null, null, this, this));
            }
            float delta = finalSelectFieldHeight - actualHeight;

            if (Math.Abs(delta) > EPS)
            {
                GetOccupiedArea().GetBBox().IncreaseHeight(delta).MoveDown(delta);
            }
            return(layoutResult);
        }
示例#2
0
        /* (non-Javadoc)
         * @see com.itextpdf.layout.renderer.BlockRenderer#layout(com.itextpdf.layout.layout.LayoutContext)
         */
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            childRenderers.Clear();
            flatRenderer = null;
            float     parentWidth  = layoutContext.GetArea().GetBBox().GetWidth();
            float     parentHeight = layoutContext.GetArea().GetBBox().GetHeight();
            IRenderer renderer     = CreateFlatRenderer();

            renderer.SetProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
            renderer.SetProperty(Property.OVERFLOW_Y, OverflowPropertyValue.VISIBLE);
            AddChild(renderer);
            Rectangle bBox = layoutContext.GetArea().GetBBox().Clone().MoveDown(INF - parentHeight).SetHeight(INF);

            layoutContext.GetArea().SetBBox(bBox);
            LayoutResult result = base.Layout(layoutContext);

            if (!childRenderers.IsEmpty())
            {
                flatRenderer = childRenderers[0];
                ProcessLangAttribute();
                childRenderers.Clear();
                childRenderers.Add(flatRenderer);
                AdjustFieldLayout(layoutContext);
                if (IsLayoutBasedOnFlatRenderer())
                {
                    Rectangle fBox = flatRenderer.GetOccupiedArea().GetBBox();
                    occupiedArea.GetBBox().SetX(fBox.GetX()).SetY(fBox.GetY()).SetWidth(fBox.GetWidth()).SetHeight(fBox.GetHeight
                                                                                                                       ());
                    ApplyPaddings(occupiedArea.GetBBox(), true);
                    ApplyBorderBox(occupiedArea.GetBBox(), true);
                    ApplyMargins(occupiedArea.GetBBox(), true);
                }
            }
            else
            {
                LogManager.GetLogger(GetType()).Error(iText.Html2pdf.LogMessageConstant.ERROR_WHILE_LAYOUT_OF_FORM_FIELD);
                occupiedArea.GetBBox().SetWidth(0).SetHeight(0);
            }
            if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) && !IsRendererFit(parentWidth, parentHeight
                                                                                                ))
            {
                occupiedArea.GetBBox().SetWidth(0).SetHeight(0);
                return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this).SetMinMaxWidth(new
                                                                                                                        MinMaxWidth()));
            }

            if (result.GetStatus() != LayoutResult.FULL || !IsRendererFit(parentWidth, parentHeight))
            {
                LogManager.GetLogger(GetType()).Warn(iText.Html2pdf.LogMessageConstant.INPUT_FIELD_DOES_NOT_FIT);
            }
            return(new MinMaxWidthLayoutResult(LayoutResult.FULL, occupiedArea, this, null).SetMinMaxWidth(new MinMaxWidth
                                                                                                               (occupiedArea.GetBBox().GetWidth(), occupiedArea.GetBBox().GetWidth(), 0)));
        }
            public override LayoutResult Layout(LayoutContext layoutContext)
            {
                LayoutResult result = base.Layout(layoutContext);

                this.entry.Value = layoutContext.GetArea().GetPageNumber();
                return(result);
            }
示例#4
0
        /* (non-Javadoc)
         * @see com.itextpdf.html2pdf.attach.impl.layout.form.renderer.AbstractFormFieldRenderer#adjustFieldLayout()
         */
        protected internal override void AdjustFieldLayout(LayoutContext layoutContext)
        {
            IList <LineRenderer> flatLines = ((ParagraphRenderer)flatRenderer).GetLines();
            Rectangle            flatBBox  = flatRenderer.GetOccupiedArea().GetBBox();

            UpdatePdfFont((ParagraphRenderer)flatRenderer);
            if (!flatLines.IsEmpty() && font != null)
            {
                if (flatLines.Count != 1)
                {
                    isSplit = true;
                }
                CropContentLines(flatLines, flatBBox);
                float?width = RetrieveWidth(layoutContext.GetArea().GetBBox().GetWidth());
                if (width == null)
                {
                    LineRenderer drawnLine = flatLines[0];
                    drawnLine.Move(flatBBox.GetX() - drawnLine.GetOccupiedArea().GetBBox().GetX(), 0);
                    flatBBox.SetWidth(drawnLine.GetOccupiedArea().GetBBox().GetWidth());
                }
            }
            else
            {
                LogManager.GetLogger(GetType()).Error(MessageFormatUtil.Format(iText.Html2pdf.LogMessageConstant.ERROR_WHILE_LAYOUT_OF_FORM_FIELD_WITH_TYPE
                                                                               , "button"));
                SetProperty(Html2PdfProperty.FORM_FIELD_FLATTEN, true);
                baseline = flatBBox.GetTop();
                flatBBox.SetY(flatBBox.GetTop()).SetHeight(0);
            }
        }
示例#5
0
            /**
             * Method adapts content, that can't be fit into the cell,
             * to prevent truncation by replacing truncated part of content with '...'
             */
            public override LayoutResult Layout(LayoutContext layoutContext)
            {
                PdfFont bf             = GetPropertyAsFont(Property.FONT);
                int     contentLength  = content.Length;
                int     leftCharIndex  = 0;
                int     rightCharIndex = contentLength - 1;

                Rectangle rect = layoutContext.GetArea().GetBBox().Clone();

                // Cell's margins, borders and paddings should be extracted from the available width as well.
                // Note that this part of the sample was introduced specifically for iText7.
                // since in iText5 the approach of processing cells was different
                ApplyBordersPaddingsMargins(rect, GetBorders(), GetPaddings());
                float availableWidth = rect.GetWidth();

                UnitValue fontSizeUV = this.GetPropertyAsUnitValue(Property.FONT_SIZE);

                // Unit values can be of POINT or PERCENT type. In this particular sample
                // the font size value is expected to be of POINT type.
                float fontSize = fontSizeUV.GetValue();

                availableWidth -= bf.GetWidth("...", fontSize);

                while (leftCharIndex < contentLength && rightCharIndex != leftCharIndex)
                {
                    availableWidth -= bf.GetWidth(content[leftCharIndex], fontSize);
                    if (availableWidth > 0)
                    {
                        leftCharIndex++;
                    }
                    else
                    {
                        break;
                    }

                    availableWidth -= bf.GetWidth(content[rightCharIndex], fontSize);

                    if (availableWidth > 0)
                    {
                        rightCharIndex--;
                    }
                    else
                    {
                        break;
                    }
                }

                // left char is the first char which should not be added
                // right char is the last char which should not be added
                String    newContent = content.Substring(0, leftCharIndex) + "..." + content.Substring(rightCharIndex + 1);
                Paragraph p          = new Paragraph(newContent);

                // We're operating on a Renderer level here, that's why we need to process a renderer,
                // created with the updated paragraph
                IRenderer pr = p.CreateRendererSubTree().SetParent(this);

                childRenderers.Add(pr);

                return(base.Layout(layoutContext));
            }
示例#6
0
        /* (non-Javadoc)
         * @see com.itextpdf.layout.renderer.TextRenderer#layout(com.itextpdf.layout.layout.LayoutContext)
         */
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            PageCountType pageCountType = (PageCountType)this.GetProperty <PageCountType?>(Html2PdfProperty.PAGE_COUNT_TYPE
                                                                                           );

            if (pageCountType == PageCountType.CURRENT_PAGE_NUMBER)
            {
                SetText(layoutContext.GetArea().GetPageNumber().ToString());
            }
            else
            {
                if (pageCountType == PageCountType.TOTAL_PAGE_COUNT)
                {
                    IRenderer rootRenderer = this;
                    while (rootRenderer is AbstractRenderer && ((AbstractRenderer)rootRenderer).GetParent() != null)
                    {
                        rootRenderer = ((AbstractRenderer)rootRenderer).GetParent();
                    }
                    if (rootRenderer is HtmlDocumentRenderer && ((HtmlDocumentRenderer)rootRenderer).GetEstimatedNumberOfPages
                            () > 0)
                    {
                        SetText(((HtmlDocumentRenderer)rootRenderer).GetEstimatedNumberOfPages().ToString());
                    }
                    else
                    {
                        if (rootRenderer is DocumentRenderer && rootRenderer.GetModelElement() is Document)
                        {
                            SetText(((Document)rootRenderer.GetModelElement()).GetPdfDocument().GetNumberOfPages().ToString());
                        }
                    }
                }
            }
            return(base.Layout(layoutContext));
        }
        public virtual LayoutResult Layout(LayoutContext layoutContext)
        {
            LayoutArea occupiedArea = layoutContext.GetArea().Clone();

            occupiedArea.GetBBox().SetHeight(0);
            occupiedArea.GetBBox().SetWidth(0);
            return(new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, null).SetAreaBreak(areaBreak));
        }
示例#8
0
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            LayoutArea area   = layoutContext.GetArea();
            float?     width  = RetrieveWidth(area.GetBBox().GetWidth());
            float?     height = this.GetPropertyAsFloat(Property.HEIGHT);

            occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(area.GetBBox().GetX(), area.GetBBox().GetY
                                                                                  () + area.GetBBox().GetHeight(), (float)width, (float)height));
            return(new LayoutResult(LayoutResult.FULL, occupiedArea, null, null));
        }
示例#9
0
            public override LayoutResult Layout(LayoutContext layoutContext)
            {
                Rectangle area = layoutContext.GetArea().GetBBox();

                LayoutContext context = new LayoutContext(new LayoutArea(layoutContext.GetArea().GetPageNumber(),
                                                                         new Rectangle(area.GetLeft(), area.GetTop() - (float)RetrieveHeight(), area.GetWidth(),
                                                                                       (float)RetrieveHeight())));

                LayoutResult result = base.Layout(context);

                // If content doesn't fit the size of a cell,
                // iTest will still return layout result full as if everything is OK.
                // As a result, the cell's content will be clipped.
                if (LayoutResult.FULL != result.GetStatus())
                {
                    return(new LayoutResult(LayoutResult.FULL, result.GetOccupiedArea(), null, null));
                }

                return(result);
            }
示例#10
0
        /// <summary><inheritDoc/></summary>
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            Rectangle parentBBox = layoutContext.GetArea().GetBBox().Clone();

            if (this.GetProperty <float?>(Property.ROTATION_ANGLE) != null)
            {
                parentBBox.MoveDown(AbstractRenderer.INF - parentBBox.GetHeight()).SetHeight(AbstractRenderer.INF);
            }
            ILineDrawer lineDrawer = this.GetProperty <ILineDrawer>(Property.LINE_DRAWER);
            float       height     = lineDrawer != null?lineDrawer.GetLineWidth() : 0;

            occupiedArea = new LayoutArea(layoutContext.GetArea().GetPageNumber(), parentBBox.Clone());
            ApplyMargins(occupiedArea.GetBBox(), false);
            float?calculatedWidth = RetrieveWidth(layoutContext.GetArea().GetBBox().GetWidth());

            if (calculatedWidth == null)
            {
                calculatedWidth = occupiedArea.GetBBox().GetWidth();
            }
            if ((occupiedArea.GetBBox().GetHeight() < height || occupiedArea.GetBBox().GetWidth() < calculatedWidth) &&
                !HasOwnProperty(Property.FORCED_PLACEMENT))
            {
                return(new LayoutResult(LayoutResult.NOTHING, null, null, this, this));
            }
            occupiedArea.GetBBox().SetWidth((float)calculatedWidth).MoveUp(occupiedArea.GetBBox().GetHeight() - height
                                                                           ).SetHeight(height);
            ApplyMargins(occupiedArea.GetBBox(), true);
            if (this.GetProperty <float?>(Property.ROTATION_ANGLE) != null)
            {
                ApplyRotationLayout(layoutContext.GetArea().GetBBox().Clone());
                if (IsNotFittingLayoutArea(layoutContext.GetArea()))
                {
                    if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                    {
                        return(new LayoutResult(LayoutResult.NOTHING, null, null, this, this));
                    }
                }
            }
            return(new LayoutResult(LayoutResult.FULL, occupiedArea, this, null));
        }
示例#11
0
        /* (non-Javadoc)
         * @see com.itextpdf.layout.renderer.TextRenderer#layout(com.itextpdf.layout.layout.LayoutContext)
         */
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            PageCountType pageCountType = (PageCountType)this.GetProperty <PageCountType?>(Html2PdfProperty.PAGE_COUNT_TYPE
                                                                                           );
            String previousText = GetText().ToString();
            // If typography is enabled and the page counter element has a non-default direction,
            // iText processes its content (see LineRenderer#updateBidiLevels) before layouting it.
            // This might result in an ArrayIndexOutOfBounds exception, because currently iText updates the page counter's content on layout.
            // To solve this, this workaround has been implemented: the renderer's strToBeConverted shouldn't be updated by layout.
            bool textHasBeenReplaced = false;

            if (pageCountType == PageCountType.CURRENT_PAGE_NUMBER)
            {
                SetText(layoutContext.GetArea().GetPageNumber().ToString());
                textHasBeenReplaced = true;
            }
            else
            {
                if (pageCountType == PageCountType.TOTAL_PAGE_COUNT)
                {
                    IRenderer rootRenderer = this;
                    while (rootRenderer is AbstractRenderer && ((AbstractRenderer)rootRenderer).GetParent() != null)
                    {
                        rootRenderer = ((AbstractRenderer)rootRenderer).GetParent();
                    }
                    if (rootRenderer is HtmlDocumentRenderer && ((HtmlDocumentRenderer)rootRenderer).GetEstimatedNumberOfPages
                            () > 0)
                    {
                        SetText(((HtmlDocumentRenderer)rootRenderer).GetEstimatedNumberOfPages().ToString());
                        textHasBeenReplaced = true;
                    }
                    else
                    {
                        if (rootRenderer is DocumentRenderer && rootRenderer.GetModelElement() is Document)
                        {
                            SetText(((Document)rootRenderer.GetModelElement()).GetPdfDocument().GetNumberOfPages().ToString());
                            textHasBeenReplaced = true;
                        }
                    }
                }
            }
            LayoutResult result = base.Layout(layoutContext);

            if (textHasBeenReplaced)
            {
                SetText(previousText);
            }
            return(result);
        }
示例#12
0
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            ILineDrawer lineDrawer = this.GetProperty <ILineDrawer>(Property.LINE_DRAWER);
            float       height     = lineDrawer != null?lineDrawer.GetLineWidth() : 0;

            occupiedArea = layoutContext.GetArea().Clone();
            ApplyMargins(occupiedArea.GetBBox(), false);
            if (occupiedArea.GetBBox().GetHeight() < height)
            {
                return(new LayoutResult(LayoutResult.NOTHING, null, null, this));
            }
            occupiedArea.GetBBox().MoveUp(occupiedArea.GetBBox().GetHeight() - height).SetHeight(height);
            ApplyMargins(occupiedArea.GetBBox(), true);
            return(new LayoutResult(LayoutResult.FULL, occupiedArea, this, null));
        }
示例#13
0
        /* (non-Javadoc)
         * @see com.itextpdf.html2pdf.attach.impl.layout.form.renderer.AbstractFormFieldRenderer#adjustFieldLayout()
         */
        protected internal override void AdjustFieldLayout(LayoutContext layoutContext)
        {
            IList <LineRenderer> flatLines = ((ParagraphRenderer)flatRenderer).GetLines();
            Rectangle            flatBBox  = flatRenderer.GetOccupiedArea().GetBBox();

            UpdatePdfFont((ParagraphRenderer)flatRenderer);
            if (!flatLines.IsEmpty() && font != null)
            {
                CropContentLines(flatLines, flatBBox);
            }
            else
            {
                LogManager.GetLogger(GetType()).Error(MessageFormatUtil.Format(iText.Html2pdf.LogMessageConstant.ERROR_WHILE_LAYOUT_OF_FORM_FIELD_WITH_TYPE
                                                                               , "text input"));
                SetProperty(Html2PdfProperty.FORM_FIELD_FLATTEN, true);
                flatBBox.SetY(flatBBox.GetTop()).SetHeight(0);
            }
            flatBBox.SetWidth((float)RetrieveWidth(layoutContext.GetArea().GetBBox().GetWidth()));
        }
示例#14
0
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            LayoutArea area      = layoutContext.GetArea().Clone();
            Rectangle  layoutBox = area.GetBBox();

            ApplyMargins(layoutBox, false);
            occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox
                                                                              .GetHeight(), 0, 0));
            width = RetrieveWidth(layoutBox.GetWidth());
            float?     angle   = this.GetPropertyAsFloat(Property.ROTATION_ANGLE);
            PdfXObject xObject = ((Image)(GetModelElement())).GetXObject();

            imageWidth     = xObject.GetWidth();
            imageHeight    = xObject.GetHeight();
            width          = width == null ? imageWidth : width;
            height         = (float)width / imageWidth * imageHeight;
            fixedXPosition = this.GetPropertyAsFloat(Property.X);
            fixedYPosition = this.GetPropertyAsFloat(Property.Y);
            float?          horizontalScaling = this.GetPropertyAsFloat(Property.HORIZONTAL_SCALING, 1f);
            float?          verticalScaling   = this.GetPropertyAsFloat(Property.VERTICAL_SCALING, 1f);
            AffineTransform t = new AffineTransform();

            if (xObject is PdfFormXObject && width != imageWidth)
            {
                horizontalScaling *= width / imageWidth;
                verticalScaling   *= height / imageHeight;
            }
            if (horizontalScaling != 1)
            {
                if (xObject is PdfFormXObject)
                {
                    t.Scale((float)horizontalScaling, 1);
                }
                width *= (float)horizontalScaling;
            }
            if (verticalScaling != 1)
            {
                if (xObject is PdfFormXObject)
                {
                    t.Scale(1, (float)verticalScaling);
                }
                height *= (float)verticalScaling;
            }
            float imageItselfScaledWidth  = (float)width;
            float imageItselfScaledHeight = (float)height;

            // See in adjustPositionAfterRotation why angle = 0 is necessary
            if (null == angle)
            {
                angle = 0f;
            }
            t.Rotate((float)angle);
            float scaleCoef = AdjustPositionAfterRotation((float)angle, layoutBox.GetWidth(), layoutBox.GetHeight());

            imageItselfScaledHeight *= scaleCoef;
            imageItselfScaledWidth  *= scaleCoef;
            if (xObject is PdfFormXObject)
            {
                t.Scale(scaleCoef, scaleCoef);
            }
            GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight);
            // indicates whether the placement is forced
            bool isPlacingForced = false;

            if (width > layoutBox.GetWidth() || height > layoutBox.GetHeight())
            {
                if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                {
                    isPlacingForced = true;
                }
                else
                {
                    return(new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this));
                }
            }
            occupiedArea.GetBBox().MoveDown(height);
            occupiedArea.GetBBox().SetHeight(height);
            occupiedArea.GetBBox().SetWidth((float)width);
            float leftMargin = (float)this.GetPropertyAsFloat(Property.MARGIN_LEFT);
            float topMargin  = (float)this.GetPropertyAsFloat(Property.MARGIN_TOP);

            if (leftMargin != 0 || topMargin != 0)
            {
                TranslateImage(leftMargin, topMargin, t);
                GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight);
            }
            ApplyMargins(occupiedArea.GetBBox(), true);
            return(new LayoutResult(LayoutResult.FULL, occupiedArea, null, null, isPlacingForced ? this : null));
        }
示例#15
0
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            Rectangle layoutBox = layoutContext.GetArea().GetBBox().Clone();

            occupiedArea = new LayoutArea(layoutContext.GetArea().GetPageNumber(), layoutBox.
                                          Clone().MoveDown(-layoutBox.GetHeight()).SetHeight(0));
            float curWidth = 0;

            maxAscent  = 0;
            maxDescent = 0;
            int           childPos      = 0;
            BaseDirection?baseDirection = this.GetProperty <BaseDirection?>(Property.BASE_DIRECTION, BaseDirection.NO_BIDI);

            foreach (IRenderer renderer in childRenderers)
            {
                if (renderer is TextRenderer)
                {
                    renderer.SetParent(this);
                    ((TextRenderer)renderer).ApplyOtf();
                    renderer.SetParent(null);
                    if (baseDirection == null || baseDirection == BaseDirection.NO_BIDI)
                    {
                        baseDirection = renderer.GetOwnProperty <BaseDirection?>(Property.BASE_DIRECTION);
                    }
                }
            }
            IList <int> unicodeIdsReorderingList = null;

            if (levels == null && baseDirection != null && baseDirection != BaseDirection.NO_BIDI)
            {
                unicodeIdsReorderingList = new List <int>();
                bool newLineFound = false;

                foreach (IRenderer child in childRenderers)
                {
                    if (newLineFound)
                    {
                        break;
                    }
                    if (child is TextRenderer)
                    {
                        GlyphLine text = ((TextRenderer)child).GetText();
                        for (int i = text.start; i < text.end; i++)
                        {
                            if (TextRenderer.IsNewLine(text, i))
                            {
                                newLineFound = true;
                                break;
                            }
                            // we assume all the chars will have the same bidi group
                            // we also assume pairing symbols won't get merged with other ones
                            unicodeIdsReorderingList.Add(text.Get(i).GetUnicode());
                        }
                    }
                }
                levels = unicodeIdsReorderingList.Count > 0 ? TypographyUtils.GetBidiLevels((BaseDirection)baseDirection, ArrayUtil.ToArray(unicodeIdsReorderingList)) : null;
            }
            bool             anythingPlaced = false;
            TabStop          nextTabStop    = null;
            LineLayoutResult result         = null;

            while (childPos < childRenderers.Count)
            {
                IRenderer    childRenderer = childRenderers[childPos];
                LayoutResult childResult;
                Rectangle    bbox = new Rectangle(layoutBox.GetX() + curWidth, layoutBox.GetY(), layoutBox
                                                  .GetWidth() - curWidth, layoutBox.GetHeight());
                if (childRenderer is TextRenderer)
                {
                    // Delete these properties in case of relayout. We might have applied them during justify().
                    childRenderer.DeleteOwnProperty(Property.CHARACTER_SPACING);
                    childRenderer.DeleteOwnProperty(Property.WORD_SPACING);
                }
                else
                {
                    if (childRenderer is TabRenderer)
                    {
                        if (nextTabStop != null)
                        {
                            IRenderer tabRenderer = childRenderers[childPos - 1];
                            tabRenderer.Layout(new LayoutContext(new LayoutArea(layoutContext.GetArea().GetPageNumber
                                                                                    (), bbox)));
                            curWidth += tabRenderer.GetOccupiedArea().GetBBox().GetWidth();
                        }
                        nextTabStop = CalculateTab(childRenderer, curWidth, layoutBox.GetWidth());
                        if (childPos == childRenderers.Count - 1)
                        {
                            nextTabStop = null;
                        }
                        if (nextTabStop != null)
                        {
                            ++childPos;
                            continue;
                        }
                    }
                }
                if (!anythingPlaced && childRenderer is TextRenderer)
                {
                    ((TextRenderer)childRenderer).TrimFirst();
                }
                if (nextTabStop != null && nextTabStop.GetTabAlignment() == TabAlignment.ANCHOR &&
                    childRenderer is TextRenderer)
                {
                    childRenderer.SetProperty(Property.TAB_ANCHOR, nextTabStop
                                              .GetTabAnchor());
                }
                childResult = childRenderer.SetParent(this).Layout(new LayoutContext(new LayoutArea
                                                                                         (layoutContext.GetArea().GetPageNumber(), bbox)));
                float childAscent  = 0;
                float childDescent = 0;
                if (childRenderer is TextRenderer)
                {
                    childAscent  = ((TextRenderer)childRenderer).GetAscent();
                    childDescent = ((TextRenderer)childRenderer).GetDescent();
                }
                else
                {
                    if (childRenderer is ImageRenderer)
                    {
                        childAscent = childRenderer.GetOccupiedArea().GetBBox().GetHeight();
                    }
                }
                maxAscent  = Math.Max(maxAscent, childAscent);
                maxDescent = Math.Min(maxDescent, childDescent);
                float maxHeight = maxAscent - maxDescent;
                if (nextTabStop != null)
                {
                    IRenderer tabRenderer = childRenderers[childPos - 1];
                    float     tabWidth    = CalculateTab(layoutBox, curWidth, nextTabStop, childRenderer, childResult
                                                         , tabRenderer);
                    tabRenderer.Layout(new LayoutContext(new LayoutArea(layoutContext.GetArea().GetPageNumber
                                                                            (), bbox)));
                    childResult.GetOccupiedArea().GetBBox().MoveRight(tabWidth);
                    if (childResult.GetSplitRenderer() != null)
                    {
                        childResult.GetSplitRenderer().GetOccupiedArea().GetBBox().MoveRight(tabWidth);
                    }
                    float tabAndNextElemWidth = tabWidth + childResult.GetOccupiedArea().GetBBox().GetWidth();
                    if (nextTabStop.GetTabAlignment() == TabAlignment.RIGHT && curWidth + tabAndNextElemWidth < nextTabStop.GetTabPosition())
                    {
                        curWidth = nextTabStop.GetTabPosition();
                    }
                    else
                    {
                        curWidth += tabAndNextElemWidth;
                    }
                    nextTabStop = null;
                }
                else
                {
                    curWidth += childResult.GetOccupiedArea().GetBBox().GetWidth();
                }
                occupiedArea.SetBBox(new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox
                                                   .GetHeight() - maxHeight, curWidth, maxHeight));
                if (childResult.GetStatus() != LayoutResult.FULL)
                {
                    LineRenderer[] split = Split();
                    split[0].childRenderers = new List <IRenderer>(childRenderers.SubList(0, childPos)
                                                                   );
                    bool wordWasSplitAndItWillFitOntoNextLine = false;
                    if (childResult is TextLayoutResult && ((TextLayoutResult)childResult).IsWordHasBeenSplit
                            ())
                    {
                        LayoutResult newLayoutResult = childRenderer.Layout(layoutContext);
                        if (newLayoutResult is TextLayoutResult && !((TextLayoutResult)newLayoutResult).IsWordHasBeenSplit
                                ())
                        {
                            wordWasSplitAndItWillFitOntoNextLine = true;
                        }
                    }
                    if (wordWasSplitAndItWillFitOntoNextLine)
                    {
                        split[1].childRenderers.Add(childRenderer);
                        split[1].childRenderers.AddAll(childRenderers.SubList(childPos + 1, childRenderers
                                                                              .Count));
                    }
                    else
                    {
                        if (childResult.GetStatus() == LayoutResult.PARTIAL)
                        {
                            split[0].AddChild(childResult.GetSplitRenderer());
                            anythingPlaced = true;
                        }
                        if (childResult.GetStatus() == LayoutResult.PARTIAL && childResult.GetOverflowRenderer
                                () is ImageRenderer)
                        {
                            ((ImageRenderer)childResult.GetOverflowRenderer()).AutoScale(layoutContext.GetArea
                                                                                             ());
                        }
                        if (null != childResult.GetOverflowRenderer())
                        {
                            split[1].childRenderers.Add(childResult.GetOverflowRenderer());
                        }
                        split[1].childRenderers.AddAll(childRenderers.SubList(childPos + 1, childRenderers
                                                                              .Count));
                        // no sense to process empty renderer
                        if (split[1].childRenderers.Count == 0)
                        {
                            split[1] = null;
                        }
                    }
                    result = new LineLayoutResult(anythingPlaced ? LayoutResult.PARTIAL : LayoutResult.NOTHING, occupiedArea, split[0], split[1],
                                                  childResult.GetStatus() == LayoutResult.NOTHING ? childResult.GetCauseOfNothing() : this);

                    if (childResult.GetStatus() == LayoutResult.PARTIAL && childResult is TextLayoutResult && ((TextLayoutResult)childResult).IsSplitForcedByNewline())
                    {
                        result.SetSplitForcedByNewline(true);
                    }
                    break;
                }
                else
                {
                    anythingPlaced = true;
                    childPos++;
                }
            }
            if (result == null)
            {
                if (anythingPlaced)
                {
                    result = new LineLayoutResult(LayoutResult.FULL, occupiedArea, null, null);
                }
                else
                {
                    result = new LineLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this);
                }
            }
            // Consider for now that all the children have the same font, and that after reordering text pieces
            // can be reordered, but cannot be split.
            if (baseDirection != null && baseDirection != BaseDirection.NO_BIDI)
            {
                IList <IRenderer> children = null;
                if (result.GetStatus() == LayoutResult.PARTIAL)
                {
                    children = result.GetSplitRenderer().GetChildRenderers();
                }
                else
                {
                    if (result.GetStatus() == LayoutResult.FULL)
                    {
                        children = GetChildRenderers();
                    }
                }
                if (children != null)
                {
                    IList <LineRenderer.RendererGlyph> lineGlyphs = new List <LineRenderer.RendererGlyph
                                                                              >();
                    foreach (IRenderer child in children)
                    {
                        if (child is TextRenderer)
                        {
                            GlyphLine childLine = ((TextRenderer)child).line;
                            for (int i = childLine.start; i < childLine.end; i++)
                            {
                                lineGlyphs.Add(new LineRenderer.RendererGlyph(childLine.Get(i), (TextRenderer)child
                                                                              ));
                            }
                        }
                    }
                    byte[] lineLevels = new byte[lineGlyphs.Count];
                    if (levels != null)
                    {
                        System.Array.Copy(levels, 0, lineLevels, 0, lineGlyphs.Count);
                    }
                    int[] reorder = TypographyUtils.ReorderLine(lineGlyphs, lineLevels, levels);
                    if (reorder != null)
                    {
                        children.Clear();
                        int           pos            = 0;
                        IList <int[]> reversedRanges = new List <int[]>();
                        int           initialPos     = 0;
                        bool          reversed       = false;
                        int           offset         = 0;
                        while (pos < lineGlyphs.Count)
                        {
                            IRenderer    renderer_1  = lineGlyphs[pos].renderer;
                            TextRenderer newRenderer = new TextRenderer((TextRenderer)renderer_1);
                            newRenderer.DeleteOwnProperty(Property.REVERSED);
                            children.Add(newRenderer);
                            ((TextRenderer)children[children.Count - 1]).line = new GlyphLine(((TextRenderer)
                                                                                               children[children.Count - 1]).line);
                            GlyphLine     gl = ((TextRenderer)children[children.Count - 1]).line;
                            IList <Glyph> replacementGlyphs = new List <Glyph>();
                            while (pos < lineGlyphs.Count && lineGlyphs[pos].renderer == renderer_1)
                            {
                                if (pos < lineGlyphs.Count - 1)
                                {
                                    if (reorder[pos] == reorder[pos + 1] + 1)
                                    {
                                        reversed = true;
                                    }
                                    else
                                    {
                                        if (reversed)
                                        {
                                            IList <int[]> reversedRange = new List <int[]>();
                                            reversedRange.Add(new int[] { initialPos - offset, pos - offset });
                                            newRenderer.SetProperty(Property.REVERSED, reversedRange);
                                            reversedRanges.Add(new int[] { initialPos - offset, pos - offset });
                                            reversed = false;
                                        }
                                        initialPos = pos + 1;
                                    }
                                }
                                replacementGlyphs.Add(lineGlyphs[pos].glyph);
                                pos++;
                            }
                            if (reversed)
                            {
                                IList <int[]> reversedRange = new List <int[]>();
                                reversedRange.Add(new int[] { initialPos - offset, pos - 1 - offset });
                                newRenderer.SetProperty(Property.REVERSED, reversedRange
                                                        );
                                reversedRanges.Add(new int[] { initialPos - offset, pos - 1 - offset });
                                reversed   = false;
                                initialPos = pos;
                            }
                            offset = initialPos;
                            gl.SetGlyphs(replacementGlyphs);
                        }
                        if (reversed)
                        {
                            if (children.Count == 1)
                            {
                                offset = 0;
                            }
                            IList <int[]> reversedRange = new List <int[]>();
                            reversedRange.Add(new int[] { initialPos - offset, pos - offset - 1 });
                            lineGlyphs[pos - 1].renderer.SetProperty(Property.REVERSED
                                                                     , reversedRange);
                            reversedRanges.Add(new int[] { initialPos - offset, pos - 1 - offset });
                        }
                        if (!reversedRanges.IsEmpty())
                        {
                            if (children.Count == 1)
                            {
                                lineGlyphs[0].renderer.SetProperty(Property.REVERSED, reversedRanges);
                            }
                        }
                        float currentXPos = layoutContext.GetArea().GetBBox().GetLeft();
                        foreach (IRenderer child_1 in children)
                        {
                            float currentWidth = ((TextRenderer)child_1).CalculateLineWidth();
                            ((TextRenderer)child_1).occupiedArea.GetBBox().SetX(currentXPos).SetWidth(currentWidth
                                                                                                      );
                            currentXPos += currentWidth;
                        }
                    }
                    if (result.GetStatus() == LayoutResult.PARTIAL)
                    {
                        LineRenderer overflow = (LineRenderer)result.GetOverflowRenderer();
                        if (levels != null)
                        {
                            overflow.levels = new byte[levels.Length - lineLevels.Length];
                            System.Array.Copy(levels, lineLevels.Length, overflow.levels, 0, overflow.levels.
                                              Length);
                            if (overflow.levels.Length == 0)
                            {
                                overflow.levels = null;
                            }
                        }
                    }
                    else if (result.GetStatus() == LayoutResult.NOTHING)
                    {
                        if (levels != null)
                        {
                            ((LineRenderer)result.GetOverflowRenderer()).levels = levels;
                        }
                    }
                }
            }
            if (anythingPlaced)
            {
                LineRenderer processed = result.GetStatus() == LayoutResult.FULL ? this : (LineRenderer
                                                                                           )result.GetSplitRenderer();
                processed.AdjustChildrenYLine().TrimLast();
            }
            return(result);
        }
        internal static LayoutResult OrphansWidowsAwareLayout(ParagraphRenderer renderer, LayoutContext context, ParagraphOrphansControl
                                                              orphansControl, ParagraphWidowsControl widowsControl)
        {
            OrphansWidowsLayoutHelper.OrphansWidowsLayoutAttempt layoutAttempt = AttemptLayout(renderer, context, context
                                                                                               .GetArea().Clone());
            if (context.IsClippedHeight() || renderer.IsPositioned() || layoutAttempt.attemptResult.GetStatus() != LayoutResult
                .PARTIAL || layoutAttempt.attemptResult.GetSplitRenderer() == null)
            {
                return(HandleAttemptAsSuccessful(layoutAttempt, context));
            }
            ParagraphRenderer splitRenderer = (ParagraphRenderer)layoutAttempt.attemptResult.GetSplitRenderer();
            bool orphansViolation           = orphansControl != null && splitRenderer != null && splitRenderer.GetLines().Count
                                              < orphansControl.GetMinOrphans() && !renderer.IsFirstOnRootArea();
            bool forcedPlacement = true.Equals(renderer.GetPropertyAsBoolean(Property.FORCED_PLACEMENT));

            if (orphansViolation && forcedPlacement)
            {
                orphansControl.HandleViolatedOrphans(splitRenderer, "Ignored orphans constraint due to forced placement.");
            }
            if (orphansViolation && !forcedPlacement)
            {
                layoutAttempt = null;
            }
            else
            {
                if (widowsControl != null && splitRenderer != null && layoutAttempt.attemptResult.GetOverflowRenderer() !=
                    null)
                {
                    ParagraphRenderer overflowRenderer = (ParagraphRenderer)layoutAttempt.attemptResult.GetOverflowRenderer();
                    // Excessively big value to check if widows constraint is violated;
                    // Make this value less in order to improve performance if you are sure
                    // that min number of widows will fit in this height. E.g. A4 page height is 842.
                    int        simulationHeight = 3500;
                    LayoutArea simulationArea   = new LayoutArea(context.GetArea().GetPageNumber(), context.GetArea().GetBBox().
                                                                 Clone().SetHeight(simulationHeight));
                    // collapsingMarginsInfo might affect available space, which is redundant in case we pass arbitrary space.
                    // floatedRendererAreas list on new area is considered empty. We don't know if there will be any, however their presence in any case will result in more widows, not less.
                    // clippedHeight is undefined for the next area, because it is defined by overflow part of the paragraph parent.
                    //               Even if it will be set to true in actual overflow-part layouting, stealing lines approach will result in
                    //               giving bigger part of MAX-HEIGHT to the overflow part and resulting in bigger number of widows, which is better.
                    //               However for possible other approaches which change content "length" (like word/char spacing adjusts),
                    //               if in actual overflow-part layouting clippedHeight will be true, those widows fixing attempts will result in worse results.
                    LayoutContext simulationContext = new LayoutContext(simulationArea);
                    LayoutResult  simulationResult  = overflowRenderer.DirectLayout(simulationContext);
                    if (simulationResult.GetStatus() == LayoutResult.FULL)
                    {
                        // simulationHeight is excessively big in order to allow to layout all of the content remaining in overflowRenderer:
                        // this way after all of the remaining content is layouted we can check if it has led to widows violation.
                        // To make this analysis possible, we expect to get result FULL.
                        // if result is PARTIAL: means that simulationHeight value isn't big enough to layout all of the content remaining in overflowRenderer.
                        // In this case we assume that widows aren't violated since the amount of the lines to fit the simulatedHeight is expected to be very large.
                        // if result is NOTHING: unexpected result, limitation of simulation approach. Retry again with forced placement set.
                        int extraWidows = widowsControl.GetMinWidows() - overflowRenderer.GetLines().Count;
                        if (extraWidows > 0)
                        {
                            int extraLinesToMove = orphansControl != null?Math.Max(orphansControl.GetMinOrphans(), 1) : 1;

                            if (extraWidows <= widowsControl.GetMaxLinesToMove() && splitRenderer.GetLines().Count - extraWidows >= extraLinesToMove
                                )
                            {
                                LineRenderer lastLine        = splitRenderer.GetLines()[splitRenderer.GetLines().Count - 1];
                                LineRenderer lastLineToLeave = splitRenderer.GetLines()[splitRenderer.GetLines().Count - extraWidows - 1];
                                float        d = lastLineToLeave.GetOccupiedArea().GetBBox().GetY() - lastLine.GetOccupiedArea().GetBBox().GetY()
                                                 - AbstractRenderer.EPS;
                                Rectangle smallerBBox = new Rectangle(context.GetArea().GetBBox());
                                smallerBBox.DecreaseHeight(d);
                                smallerBBox.MoveUp(d);
                                LayoutArea smallerAvailableArea = new LayoutArea(context.GetArea().GetPageNumber(), smallerBBox);
                                layoutAttempt = AttemptLayout(renderer, context, smallerAvailableArea);
                            }
                            else
                            {
                                if (forcedPlacement || renderer.IsFirstOnRootArea() || !widowsControl.IsOverflowOnWidowsViolation())
                                {
                                    if (forcedPlacement)
                                    {
                                        widowsControl.HandleViolatedWidows(overflowRenderer, "forced placement");
                                    }
                                    else
                                    {
                                        widowsControl.HandleViolatedWidows(overflowRenderer, "inability to fix it");
                                    }
                                }
                                else
                                {
                                    layoutAttempt = null;
                                }
                            }
                        }
                    }
                }
            }
            if (layoutAttempt != null)
            {
                return(HandleAttemptAsSuccessful(layoutAttempt, context));
            }
            else
            {
                return(new LayoutResult(LayoutResult.NOTHING, null, null, renderer));
            }
        }
示例#17
0
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            LayoutArea      area         = layoutContext.GetArea().Clone();
            Rectangle       layoutBox    = area.GetBBox().Clone();
            AffineTransform t            = new AffineTransform();
            Image           modelElement = (Image)(GetModelElement());
            PdfXObject      xObject      = modelElement.GetXObject();

            imageWidth  = modelElement.GetImageWidth();
            imageHeight = modelElement.GetImageHeight();
            CalculateImageDimensions(layoutBox, t, xObject);
            OverflowPropertyValue?overflowX = null != parent?parent.GetProperty <OverflowPropertyValue?>(Property.OVERFLOW_X
                                                                                                         ) : OverflowPropertyValue.FIT;

            bool nowrap = false;

            if (parent is LineRenderer)
            {
                nowrap = true.Equals(this.parent.GetOwnProperty <bool?>(Property.NO_SOFT_WRAP_INLINE));
            }
            IList <Rectangle> floatRendererAreas    = layoutContext.GetFloatRendererAreas();
            float             clearHeightCorrection = FloatingHelper.CalculateClearHeightCorrection(this, floatRendererAreas, layoutBox
                                                                                                    );
            FloatPropertyValue?floatPropertyValue = this.GetProperty <FloatPropertyValue?>(Property.FLOAT);

            if (FloatingHelper.IsRendererFloating(this, floatPropertyValue))
            {
                layoutBox.DecreaseHeight(clearHeightCorrection);
                FloatingHelper.AdjustFloatedBlockLayoutBox(this, layoutBox, width, floatRendererAreas, floatPropertyValue,
                                                           overflowX);
            }
            else
            {
                clearHeightCorrection = FloatingHelper.AdjustLayoutBoxAccordingToFloats(floatRendererAreas, layoutBox, width
                                                                                        , clearHeightCorrection, null);
            }
            ApplyMargins(layoutBox, false);
            Border[] borders = GetBorders();
            ApplyBorderBox(layoutBox, borders, false);
            float?declaredMaxHeight         = RetrieveMaxHeight();
            OverflowPropertyValue?overflowY = null == parent || ((null == declaredMaxHeight || declaredMaxHeight > layoutBox
                                                                  .GetHeight()) && !layoutContext.IsClippedHeight()) ? OverflowPropertyValue.FIT : parent.GetProperty <OverflowPropertyValue?
                                                                                                                                                                       >(Property.OVERFLOW_Y);
            bool processOverflowX = !IsOverflowFit(overflowX) || nowrap;
            bool processOverflowY = !IsOverflowFit(overflowY);

            if (IsAbsolutePosition())
            {
                ApplyAbsolutePosition(layoutBox);
            }
            occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox
                                                                              .GetHeight(), 0, 0));
            float imageItselfScaledWidth  = (float)width;
            float imageItselfScaledHeight = (float)height;

            if (IsFixedLayout())
            {
                fixedXPosition = this.GetPropertyAsFloat(Property.LEFT);
                fixedYPosition = this.GetPropertyAsFloat(Property.BOTTOM);
            }
            float?angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE);

            // See in adjustPositionAfterRotation why angle = 0 is necessary
            if (null == angle)
            {
                angle = 0f;
            }
            t.Rotate((float)angle);
            initialOccupiedAreaBBox = GetOccupiedAreaBBox().Clone();
            float scaleCoef = AdjustPositionAfterRotation((float)angle, layoutBox.GetWidth(), layoutBox.GetHeight());

            imageItselfScaledHeight *= scaleCoef;
            imageItselfScaledWidth  *= scaleCoef;
            initialOccupiedAreaBBox.MoveDown(imageItselfScaledHeight);
            initialOccupiedAreaBBox.SetHeight(imageItselfScaledHeight);
            initialOccupiedAreaBBox.SetWidth(imageItselfScaledWidth);
            if (xObject is PdfFormXObject)
            {
                t.Scale(scaleCoef, scaleCoef);
            }
            GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight);
            // indicates whether the placement is forced
            bool isPlacingForced = false;

            if (width > layoutBox.GetWidth() || height > layoutBox.GetHeight())
            {
                if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) || (width > layoutBox.GetWidth() && processOverflowX
                                                                                     ) || (height > layoutBox.GetHeight() && processOverflowY))
                {
                    isPlacingForced = true;
                }
                else
                {
                    ApplyMargins(initialOccupiedAreaBBox, true);
                    ApplyBorderBox(initialOccupiedAreaBBox, true);
                    occupiedArea.GetBBox().SetHeight(initialOccupiedAreaBBox.GetHeight());
                    return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this));
                }
            }
            occupiedArea.GetBBox().MoveDown((float)height);
            if (borders[3] != null)
            {
                height += (float)Math.Sin((float)angle) * borders[3].GetWidth();
            }
            occupiedArea.GetBBox().SetHeight((float)height);
            occupiedArea.GetBBox().SetWidth((float)width);
            UnitValue leftMargin = this.GetPropertyAsUnitValue(Property.MARGIN_LEFT);

            if (!leftMargin.IsPointValue())
            {
                ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ImageRenderer));
                logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property
                                                      .MARGIN_LEFT));
            }
            UnitValue topMargin = this.GetPropertyAsUnitValue(Property.MARGIN_TOP);

            if (!topMargin.IsPointValue())
            {
                ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ImageRenderer));
                logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property
                                                      .MARGIN_TOP));
            }
            if (0 != leftMargin.GetValue() || 0 != topMargin.GetValue())
            {
                TranslateImage(leftMargin.GetValue(), topMargin.GetValue(), t);
                GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight);
            }
            ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
            ApplyMargins(occupiedArea.GetBBox(), true);
            if (angle != 0)
            {
                ApplyRotationLayout((float)angle);
            }
            float       unscaledWidth = occupiedArea.GetBBox().GetWidth() / scaleCoef;
            MinMaxWidth minMaxWidth   = new MinMaxWidth(unscaledWidth, unscaledWidth, 0);
            UnitValue   rendererWidth = this.GetProperty <UnitValue>(Property.WIDTH);

            if (rendererWidth != null && rendererWidth.IsPercentValue())
            {
                minMaxWidth.SetChildrenMinWidth(0);
                float coeff = imageWidth / (float)RetrieveWidth(area.GetBBox().GetWidth());
                minMaxWidth.SetChildrenMaxWidth(unscaledWidth * coeff);
            }
            else
            {
                bool autoScale      = HasProperty(Property.AUTO_SCALE) && (bool)this.GetProperty <bool?>(Property.AUTO_SCALE);
                bool autoScaleWidth = HasProperty(Property.AUTO_SCALE_WIDTH) && (bool)this.GetProperty <bool?>(Property.AUTO_SCALE_WIDTH
                                                                                                               );
                if (autoScale || autoScaleWidth)
                {
                    minMaxWidth.SetChildrenMinWidth(0);
                }
            }
            FloatingHelper.RemoveFloatsAboveRendererBottom(floatRendererAreas, this);
            LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, floatRendererAreas,
                                                                                            layoutContext.GetArea().GetBBox(), clearHeightCorrection, false);

            ApplyAbsolutePositionIfNeeded(layoutContext);
            return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea, null, null, isPlacingForced ? this : null
                                               ).SetMinMaxWidth(minMaxWidth));
        }
        protected internal virtual LayoutResult DirectLayout(LayoutContext layoutContext)
        {
            bool                   wasHeightClipped        = false;
            bool                   wasParentsHeightClipped = layoutContext.IsClippedHeight();
            int                    pageNumber               = layoutContext.GetArea().GetPageNumber();
            bool                   anythingPlaced           = false;
            bool                   firstLineInBox           = true;
            LineRenderer           currentRenderer          = (LineRenderer) new LineRenderer().SetParent(this);
            Rectangle              parentBBox               = layoutContext.GetArea().GetBBox().Clone();
            MarginsCollapseHandler marginsCollapseHandler   = null;
            bool                   marginsCollapsingEnabled = true.Equals(GetPropertyAsBoolean(Property.COLLAPSING_MARGINS));

            if (marginsCollapsingEnabled)
            {
                marginsCollapseHandler = new MarginsCollapseHandler(this, layoutContext.GetMarginsCollapseInfo());
            }
            OverflowPropertyValue?overflowX = this.GetProperty <OverflowPropertyValue?>(Property.OVERFLOW_X);
            bool?nowrapProp = this.GetPropertyAsBoolean(Property.NO_SOFT_WRAP_INLINE);

            currentRenderer.SetProperty(Property.NO_SOFT_WRAP_INLINE, nowrapProp);
            bool notAllKidsAreFloats = false;
            IList <Rectangle>  floatRendererAreas = layoutContext.GetFloatRendererAreas();
            FloatPropertyValue?floatPropertyValue = this.GetProperty <FloatPropertyValue?>(Property.FLOAT);
            float clearHeightCorrection           = FloatingHelper.CalculateClearHeightCorrection(this, floatRendererAreas, parentBBox
                                                                                                  );

            FloatingHelper.ApplyClearance(parentBBox, marginsCollapseHandler, clearHeightCorrection, FloatingHelper.IsRendererFloating
                                              (this));
            float?blockWidth = RetrieveWidth(parentBBox.GetWidth());

            if (FloatingHelper.IsRendererFloating(this, floatPropertyValue))
            {
                blockWidth = FloatingHelper.AdjustFloatedBlockLayoutBox(this, parentBBox, blockWidth, floatRendererAreas,
                                                                        floatPropertyValue, overflowX);
                floatRendererAreas = new List <Rectangle>();
            }
            if (0 == childRenderers.Count)
            {
                anythingPlaced  = true;
                currentRenderer = null;
            }
            bool  isPositioned              = IsPositioned();
            float?rotation                  = this.GetPropertyAsFloat(Property.ROTATION_ANGLE);
            float?blockMaxHeight            = RetrieveMaxHeight();
            OverflowPropertyValue?overflowY = (null == blockMaxHeight || blockMaxHeight > parentBBox.GetHeight()) &&
                                              !wasParentsHeightClipped ? OverflowPropertyValue.FIT : this.GetProperty <OverflowPropertyValue?>(Property
                                                                                                                                               .OVERFLOW_Y);

            if (rotation != null || IsFixedLayout())
            {
                parentBBox.MoveDown(AbstractRenderer.INF - parentBBox.GetHeight()).SetHeight(AbstractRenderer.INF);
            }
            if (rotation != null && !FloatingHelper.IsRendererFloating(this))
            {
                blockWidth = RotationUtils.RetrieveRotatedLayoutWidth(parentBBox.GetWidth(), this);
            }
            if (marginsCollapsingEnabled)
            {
                marginsCollapseHandler.StartMarginsCollapse(parentBBox);
            }
            Border[]    borders         = GetBorders();
            UnitValue[] paddings        = GetPaddings();
            float       additionalWidth = ApplyBordersPaddingsMargins(parentBBox, borders, paddings);

            ApplyWidth(parentBBox, blockWidth, overflowX);
            wasHeightClipped = ApplyMaxHeight(parentBBox, blockMaxHeight, marginsCollapseHandler, false, wasParentsHeightClipped
                                              , overflowY);
            MinMaxWidth          minMaxWidth  = new MinMaxWidth(additionalWidth);
            AbstractWidthHandler widthHandler = new MaxMaxWidthHandler(minMaxWidth);
            IList <Rectangle>    areas;

            if (isPositioned)
            {
                areas = JavaCollectionsUtil.SingletonList(parentBBox);
            }
            else
            {
                areas = InitElementAreas(new LayoutArea(pageNumber, parentBBox));
            }
            occupiedArea = new LayoutArea(pageNumber, new Rectangle(parentBBox.GetX(), parentBBox.GetY() + parentBBox.
                                                                    GetHeight(), parentBBox.GetWidth(), 0));
            ShrinkOccupiedAreaForAbsolutePosition();
            int       currentAreaPos = 0;
            Rectangle layoutBox      = areas[0].Clone();

            lines = new List <LineRenderer>();
            foreach (IRenderer child in childRenderers)
            {
                notAllKidsAreFloats = notAllKidsAreFloats || !FloatingHelper.IsRendererFloating(child);
                currentRenderer.AddChild(child);
            }
            float             lastYLine                            = layoutBox.GetY() + layoutBox.GetHeight();
            float             previousDescent                      = 0;
            float             lastLineBottomLeadingIndent          = 0;
            bool              onlyOverflowedFloatsLeft             = false;
            IList <IRenderer> inlineFloatsOverflowedToNextPage     = new List <IRenderer>();
            bool              floatOverflowedToNextPageWithNothing = false;
            // rectangles are compared by instances
            ICollection <Rectangle> nonChildFloatingRendererAreas = new HashSet <Rectangle>(floatRendererAreas);

            if (marginsCollapsingEnabled && childRenderers.Count > 0)
            {
                // passing null is sufficient to notify that there is a kid, however we don't care about it and it's margins
                marginsCollapseHandler.StartChildMarginsHandling(null, layoutBox);
            }
            bool includeFloatsInOccupiedArea = BlockFormattingContextUtil.IsRendererCreateBfc(this);

            while (currentRenderer != null)
            {
                currentRenderer.SetProperty(Property.TAB_DEFAULT, this.GetPropertyAsFloat(Property.TAB_DEFAULT));
                currentRenderer.SetProperty(Property.TAB_STOPS, this.GetProperty <Object>(Property.TAB_STOPS));
                float     lineIndent     = anythingPlaced ? 0 : (float)this.GetPropertyAsFloat(Property.FIRST_LINE_INDENT);
                Rectangle childLayoutBox = new Rectangle(layoutBox.GetX(), layoutBox.GetY(), layoutBox.GetWidth(), layoutBox
                                                         .GetHeight());
                currentRenderer.SetProperty(Property.OVERFLOW_X, overflowX);
                currentRenderer.SetProperty(Property.OVERFLOW_Y, overflowY);
                LineLayoutContext lineLayoutContext = new LineLayoutContext(new LayoutArea(pageNumber, childLayoutBox), null
                                                                            , floatRendererAreas, wasHeightClipped || wasParentsHeightClipped).SetTextIndent(lineIndent).SetFloatOverflowedToNextPageWithNothing
                                                          (floatOverflowedToNextPageWithNothing);
                LineLayoutResult result = (LineLayoutResult)((LineRenderer)currentRenderer.SetParent(this)).Layout(lineLayoutContext
                                                                                                                   );
                if (result.GetStatus() == LayoutResult.NOTHING)
                {
                    float?lineShiftUnderFloats = FloatingHelper.CalculateLineShiftUnderFloats(floatRendererAreas, layoutBox);
                    if (lineShiftUnderFloats != null)
                    {
                        layoutBox.DecreaseHeight((float)lineShiftUnderFloats);
                        firstLineInBox = true;
                        continue;
                    }
                    bool allRemainingKidsAreFloats = !currentRenderer.childRenderers.IsEmpty();
                    foreach (IRenderer renderer in currentRenderer.childRenderers)
                    {
                        allRemainingKidsAreFloats = allRemainingKidsAreFloats && FloatingHelper.IsRendererFloating(renderer);
                    }
                    if (allRemainingKidsAreFloats)
                    {
                        onlyOverflowedFloatsLeft = true;
                    }
                }
                floatOverflowedToNextPageWithNothing = lineLayoutContext.IsFloatOverflowedToNextPageWithNothing();
                if (result.GetFloatsOverflowedToNextPage() != null)
                {
                    inlineFloatsOverflowedToNextPage.AddAll(result.GetFloatsOverflowedToNextPage());
                }
                float minChildWidth = 0;
                float maxChildWidth = 0;
                if (result is MinMaxWidthLayoutResult)
                {
                    minChildWidth = ((MinMaxWidthLayoutResult)result).GetMinMaxWidth().GetMinWidth();
                    maxChildWidth = ((MinMaxWidthLayoutResult)result).GetMinMaxWidth().GetMaxWidth();
                }
                widthHandler.UpdateMinChildWidth(minChildWidth);
                widthHandler.UpdateMaxChildWidth(maxChildWidth);
                LineRenderer processedRenderer = null;
                if (result.GetStatus() == LayoutResult.FULL)
                {
                    processedRenderer = currentRenderer;
                }
                else
                {
                    if (result.GetStatus() == LayoutResult.PARTIAL)
                    {
                        processedRenderer = (LineRenderer)result.GetSplitRenderer();
                    }
                }
                if (onlyOverflowedFloatsLeft)
                {
                    // This is done to trick ParagraphRenderer to break rendering and to overflow to the next page.
                    // The `onlyOverflowedFloatsLeft` is set to true only when no other content is left except
                    // overflowed floating elements.
                    processedRenderer = null;
                }
                TextAlignment?textAlignment = (TextAlignment?)this.GetProperty <TextAlignment?>(Property.TEXT_ALIGNMENT, TextAlignment
                                                                                                .LEFT);
                ApplyTextAlignment(textAlignment, result, processedRenderer, layoutBox, floatRendererAreas, onlyOverflowedFloatsLeft
                                   , lineIndent);
                Leading leading = RenderingMode.HTML_MODE.Equals(this.GetProperty <RenderingMode?>(Property.RENDERING_MODE)
                                                                 ) ? null : this.GetProperty <Leading>(Property.LEADING);
                // could be false if e.g. line contains only floats
                bool lineHasContent = processedRenderer != null && processedRenderer.GetOccupiedArea().GetBBox().GetHeight
                                          () > 0;
                bool  isFit  = processedRenderer != null;
                float deltaY = 0;
                if (isFit && !RenderingMode.HTML_MODE.Equals(this.GetProperty <RenderingMode?>(Property.RENDERING_MODE)))
                {
                    if (lineHasContent)
                    {
                        float indentFromLastLine = previousDescent - lastLineBottomLeadingIndent - (leading != null ? processedRenderer
                                                                                                    .GetTopLeadingIndent(leading) : 0) - processedRenderer.GetMaxAscent();
                        // TODO this is a workaround. To be refactored
                        if (processedRenderer != null && processedRenderer.ContainsImage())
                        {
                            indentFromLastLine += previousDescent;
                        }
                        deltaY = lastYLine + indentFromLastLine - processedRenderer.GetYLine();
                        lastLineBottomLeadingIndent = leading != null?processedRenderer.GetBottomLeadingIndent(leading) : 0;

                        // TODO this is a workaround. To be refactored
                        if (lastLineBottomLeadingIndent < 0 && processedRenderer.ContainsImage())
                        {
                            lastLineBottomLeadingIndent = 0;
                        }
                    }
                    // for the first and last line in a paragraph, leading is smaller
                    if (firstLineInBox)
                    {
                        deltaY = processedRenderer != null && leading != null ? -processedRenderer.GetTopLeadingIndent(leading) :
                                 0;
                    }
                    isFit = leading == null || processedRenderer.GetOccupiedArea().GetBBox().GetY() + deltaY >= layoutBox.GetY
                                ();
                }
                if (!isFit && (null == processedRenderer || IsOverflowFit(overflowY)))
                {
                    if (currentAreaPos + 1 < areas.Count)
                    {
                        layoutBox      = areas[++currentAreaPos].Clone();
                        lastYLine      = layoutBox.GetY() + layoutBox.GetHeight();
                        firstLineInBox = true;
                    }
                    else
                    {
                        bool keepTogether = IsKeepTogether();
                        if (keepTogether)
                        {
                            floatRendererAreas.RetainAll(nonChildFloatingRendererAreas);
                            return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, null, null, this, null == result.GetCauseOfNothing
                                                                   () ? this : result.GetCauseOfNothing()));
                        }
                        else
                        {
                            if (marginsCollapsingEnabled)
                            {
                                if (anythingPlaced && notAllKidsAreFloats)
                                {
                                    marginsCollapseHandler.EndChildMarginsHandling(layoutBox);
                                }
                            }
                            // On page split, if not only overflowed floats left, content will be drawn on next page, i.e. under all floats on this page
                            bool includeFloatsInOccupiedAreaOnSplit = !onlyOverflowedFloatsLeft || includeFloatsInOccupiedArea;
                            if (includeFloatsInOccupiedAreaOnSplit)
                            {
                                FloatingHelper.IncludeChildFloatsInOccupiedArea(floatRendererAreas, this, nonChildFloatingRendererAreas);
                                FixOccupiedAreaIfOverflowedX(overflowX, layoutBox);
                            }
                            if (marginsCollapsingEnabled)
                            {
                                marginsCollapseHandler.EndMarginsCollapse(layoutBox);
                            }
                            bool minHeightOverflowed = false;
                            if (!includeFloatsInOccupiedAreaOnSplit)
                            {
                                AbstractRenderer minHeightOverflow = ApplyMinHeight(overflowY, layoutBox);
                                minHeightOverflowed = minHeightOverflow != null;
                                ApplyVerticalAlignment();
                            }
                            iText.Layout.Renderer.ParagraphRenderer[] split = Split();
                            split[0].lines = lines;
                            foreach (LineRenderer line in lines)
                            {
                                split[0].childRenderers.AddAll(line.GetChildRenderers());
                            }
                            split[1].childRenderers.AddAll(inlineFloatsOverflowedToNextPage);
                            if (processedRenderer != null)
                            {
                                split[1].childRenderers.AddAll(processedRenderer.GetChildRenderers());
                            }
                            if (result.GetOverflowRenderer() != null)
                            {
                                split[1].childRenderers.AddAll(result.GetOverflowRenderer().GetChildRenderers());
                            }
                            if (onlyOverflowedFloatsLeft && !includeFloatsInOccupiedArea && !minHeightOverflowed)
                            {
                                FloatingHelper.RemoveParentArtifactsOnPageSplitIfOnlyFloatsOverflow(split[1]);
                            }
                            float usedHeight = occupiedArea.GetBBox().GetHeight();
                            if (!includeFloatsInOccupiedAreaOnSplit)
                            {
                                Rectangle commonRectangle = Rectangle.GetCommonRectangle(layoutBox, occupiedArea.GetBBox());
                                usedHeight = commonRectangle.GetHeight();
                            }
                            UpdateHeightsOnSplit(usedHeight, wasHeightClipped, this, split[1], includeFloatsInOccupiedAreaOnSplit);
                            CorrectFixedLayout(layoutBox);
                            ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
                            ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
                            ApplyMargins(occupiedArea.GetBBox(), true);
                            ApplyAbsolutePositionIfNeeded(layoutContext);
                            LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, layoutContext.GetFloatRendererAreas
                                                                                                                (), layoutContext.GetArea().GetBBox(), clearHeightCorrection, marginsCollapsingEnabled);
                            if (wasHeightClipped)
                            {
                                return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea, split[0], null).SetMinMaxWidth(minMaxWidth
                                                                                                                                 ));
                            }
                            else
                            {
                                if (anythingPlaced)
                                {
                                    return(new MinMaxWidthLayoutResult(LayoutResult.PARTIAL, editedArea, split[0], split[1]).SetMinMaxWidth(minMaxWidth
                                                                                                                                            ));
                                }
                                else
                                {
                                    if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                                    {
                                        occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), currentRenderer.GetOccupiedArea(
                                                                                              ).GetBBox()));
                                        FixOccupiedAreaIfOverflowedX(overflowX, layoutBox);
                                        parent.SetProperty(Property.FULL, true);
                                        lines.Add(currentRenderer);
                                        // Force placement of children we have and do not force placement of the others
                                        if (LayoutResult.PARTIAL == result.GetStatus())
                                        {
                                            IRenderer childNotRendered = result.GetCauseOfNothing();
                                            int       firstNotRendered = currentRenderer.childRenderers.IndexOf(childNotRendered);
                                            currentRenderer.childRenderers.RetainAll(currentRenderer.childRenderers.SubList(0, firstNotRendered));
                                            split[1].childRenderers.RemoveAll(split[1].childRenderers.SubList(0, firstNotRendered));
                                            return(new MinMaxWidthLayoutResult(LayoutResult.PARTIAL, editedArea, this, split[1], null).SetMinMaxWidth(
                                                       minMaxWidth));
                                        }
                                        else
                                        {
                                            return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea, null, null, this).SetMinMaxWidth(minMaxWidth
                                                                                                                                               ));
                                        }
                                    }
                                    else
                                    {
                                        floatRendererAreas.RetainAll(nonChildFloatingRendererAreas);
                                        return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, null, null, this, null == result.GetCauseOfNothing
                                                                               () ? this : result.GetCauseOfNothing()));
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (leading != null)
                    {
                        processedRenderer.ApplyLeading(deltaY);
                        if (lineHasContent)
                        {
                            lastYLine = processedRenderer.GetYLine();
                        }
                    }
                    if (lineHasContent)
                    {
                        occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), processedRenderer.GetOccupiedArea
                                                                              ().GetBBox()));
                        FixOccupiedAreaIfOverflowedX(overflowX, layoutBox);
                    }
                    firstLineInBox = false;
                    layoutBox.SetHeight(processedRenderer.GetOccupiedArea().GetBBox().GetY() - layoutBox.GetY());
                    lines.Add(processedRenderer);
                    anythingPlaced  = true;
                    currentRenderer = (LineRenderer)result.GetOverflowRenderer();
                    previousDescent = processedRenderer.GetMaxDescent();
                    if (!inlineFloatsOverflowedToNextPage.IsEmpty() && result.GetOverflowRenderer() == null)
                    {
                        onlyOverflowedFloatsLeft = true;
                        // dummy renderer to trick paragraph renderer to continue kids loop
                        currentRenderer = new LineRenderer();
                    }
                }
            }
            if (!RenderingMode.HTML_MODE.Equals(this.GetProperty <RenderingMode?>(Property.RENDERING_MODE)))
            {
                float moveDown = lastLineBottomLeadingIndent;
                if (IsOverflowFit(overflowY) && moveDown > occupiedArea.GetBBox().GetY() - layoutBox.GetY())
                {
                    moveDown = occupiedArea.GetBBox().GetY() - layoutBox.GetY();
                }
                occupiedArea.GetBBox().MoveDown(moveDown);
                occupiedArea.GetBBox().SetHeight(occupiedArea.GetBBox().GetHeight() + moveDown);
            }
            if (marginsCollapsingEnabled)
            {
                if (childRenderers.Count > 0 && notAllKidsAreFloats)
                {
                    marginsCollapseHandler.EndChildMarginsHandling(layoutBox);
                }
            }
            if (includeFloatsInOccupiedArea)
            {
                FloatingHelper.IncludeChildFloatsInOccupiedArea(floatRendererAreas, this, nonChildFloatingRendererAreas);
                FixOccupiedAreaIfOverflowedX(overflowX, layoutBox);
            }
            if (wasHeightClipped)
            {
                FixOccupiedAreaIfOverflowedY(overflowY, layoutBox);
            }
            if (marginsCollapsingEnabled)
            {
                marginsCollapseHandler.EndMarginsCollapse(layoutBox);
            }
            AbstractRenderer overflowRenderer = ApplyMinHeight(overflowY, layoutBox);

            if (overflowRenderer != null && IsKeepTogether())
            {
                floatRendererAreas.RetainAll(nonChildFloatingRendererAreas);
                return(new LayoutResult(LayoutResult.NOTHING, null, null, this, this));
            }
            CorrectFixedLayout(layoutBox);
            ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
            ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
            ApplyMargins(occupiedArea.GetBBox(), true);
            ApplyAbsolutePositionIfNeeded(layoutContext);
            if (rotation != null)
            {
                ApplyRotationLayout(layoutContext.GetArea().GetBBox().Clone());
                if (IsNotFittingLayoutArea(layoutContext.GetArea()))
                {
                    if (IsNotFittingWidth(layoutContext.GetArea()) && !IsNotFittingHeight(layoutContext.GetArea()))
                    {
                        LogManager.GetLogger(GetType()).Warn(MessageFormatUtil.Format(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA
                                                                                      , "It fits by height so it will be forced placed"));
                    }
                    else
                    {
                        if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                        {
                            floatRendererAreas.RetainAll(nonChildFloatingRendererAreas);
                            return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, null, null, this, this));
                        }
                    }
                }
            }
            ApplyVerticalAlignment();
            FloatingHelper.RemoveFloatsAboveRendererBottom(floatRendererAreas, this);
            LayoutArea editedArea_1 = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, layoutContext.GetFloatRendererAreas
                                                                                                  (), layoutContext.GetArea().GetBBox(), clearHeightCorrection, marginsCollapsingEnabled);

            if (null == overflowRenderer)
            {
                return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea_1, null, null, null).SetMinMaxWidth(minMaxWidth
                                                                                                                     ));
            }
            else
            {
                return(new MinMaxWidthLayoutResult(LayoutResult.PARTIAL, editedArea_1, this, overflowRenderer, null).SetMinMaxWidth
                           (minMaxWidth));
            }
        }
示例#19
0
        /// <summary><inheritDoc/></summary>
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            int          pageNumber      = layoutContext.GetArea().GetPageNumber();
            bool         anythingPlaced  = false;
            bool         firstLineInBox  = true;
            LineRenderer currentRenderer = (LineRenderer) new LineRenderer().SetParent(this);
            Rectangle    parentBBox      = layoutContext.GetArea().GetBBox().Clone();

            if (0 == childRenderers.Count)
            {
                anythingPlaced  = true;
                currentRenderer = null;
                SetProperty(Property.MARGIN_TOP, 0);
                SetProperty(Property.MARGIN_RIGHT, 0);
                SetProperty(Property.MARGIN_BOTTOM, 0);
                SetProperty(Property.MARGIN_LEFT, 0);
                SetProperty(Property.PADDING_TOP, 0);
                SetProperty(Property.PADDING_RIGHT, 0);
                SetProperty(Property.PADDING_BOTTOM, 0);
                SetProperty(Property.PADDING_LEFT, 0);
                SetProperty(Property.BORDER, Border.NO_BORDER);
            }
            if (this.GetProperty <float?>(Property.ROTATION_ANGLE) != null)
            {
                parentBBox.MoveDown(AbstractRenderer.INF - parentBBox.GetHeight()).SetHeight(AbstractRenderer.INF);
            }
            float[] margins = GetMargins();
            ApplyMargins(parentBBox, margins, false);
            Border[] borders = GetBorders();
            ApplyBorderBox(parentBBox, borders, false);
            bool isPositioned = IsPositioned();

            if (isPositioned)
            {
                float x         = (float)this.GetPropertyAsFloat(Property.X);
                float relativeX = IsFixedLayout() ? 0 : parentBBox.GetX();
                parentBBox.SetX(relativeX + x);
            }
            float?blockWidth = RetrieveWidth(parentBBox.GetWidth());

            if (blockWidth != null && (blockWidth < parentBBox.GetWidth() || isPositioned))
            {
                parentBBox.SetWidth((float)blockWidth);
            }
            float[] paddings = GetPaddings();
            ApplyPaddings(parentBBox, paddings, false);
            IList <Rectangle> areas;

            if (isPositioned)
            {
                areas = JavaCollectionsUtil.SingletonList(parentBBox);
            }
            else
            {
                areas = InitElementAreas(new LayoutArea(pageNumber, parentBBox));
            }
            occupiedArea = new LayoutArea(pageNumber, new Rectangle(parentBBox.GetX(), parentBBox.GetY() + parentBBox.
                                                                    GetHeight(), parentBBox.GetWidth(), 0));
            int       currentAreaPos = 0;
            Rectangle layoutBox      = areas[0].Clone();

            lines = new List <LineRenderer>();
            foreach (IRenderer child in childRenderers)
            {
                currentRenderer.AddChild(child);
            }
            float   lastYLine      = layoutBox.GetY() + layoutBox.GetHeight();
            Leading leading        = this.GetProperty <Leading>(Property.LEADING);
            float   leadingValue   = 0;
            float   lastLineHeight = 0;

            while (currentRenderer != null)
            {
                currentRenderer.SetProperty(Property.TAB_DEFAULT, this.GetPropertyAsFloat(Property.TAB_DEFAULT));
                currentRenderer.SetProperty(Property.TAB_STOPS, this.GetProperty <Object>(Property.TAB_STOPS));
                float     lineIndent     = anythingPlaced ? 0 : (float)this.GetPropertyAsFloat(Property.FIRST_LINE_INDENT);
                float     availableWidth = layoutBox.GetWidth() - lineIndent;
                Rectangle childLayoutBox = new Rectangle(layoutBox.GetX() + lineIndent, layoutBox.GetY(), availableWidth,
                                                         layoutBox.GetHeight());
                LineLayoutResult result = ((LineLayoutResult)((LineRenderer)currentRenderer.SetParent(this)).Layout(new LayoutContext
                                                                                                                        (new LayoutArea(pageNumber, childLayoutBox))));
                LineRenderer processedRenderer = null;
                if (result.GetStatus() == LayoutResult.FULL)
                {
                    processedRenderer = currentRenderer;
                }
                else
                {
                    if (result.GetStatus() == LayoutResult.PARTIAL)
                    {
                        processedRenderer = (LineRenderer)result.GetSplitRenderer();
                    }
                }
                TextAlignment?textAlignment = (TextAlignment?)this.GetProperty <TextAlignment?>(Property.TEXT_ALIGNMENT, TextAlignment
                                                                                                .LEFT);
                if (result.GetStatus() == LayoutResult.PARTIAL && textAlignment == TextAlignment.JUSTIFIED && !result.IsSplitForcedByNewline
                        () || textAlignment == TextAlignment.JUSTIFIED_ALL)
                {
                    if (processedRenderer != null)
                    {
                        processedRenderer.Justify(layoutBox.GetWidth() - lineIndent);
                    }
                }
                else
                {
                    if (textAlignment != TextAlignment.LEFT && processedRenderer != null)
                    {
                        float deltaX = availableWidth - processedRenderer.GetOccupiedArea().GetBBox().GetWidth();
                        switch (textAlignment)
                        {
                        case TextAlignment.RIGHT: {
                            processedRenderer.Move(deltaX, 0);
                            break;
                        }

                        case TextAlignment.CENTER: {
                            processedRenderer.Move(deltaX / 2, 0);
                            break;
                        }
                        }
                    }
                }
                leadingValue = processedRenderer != null && leading != null?processedRenderer.GetLeadingValue(leading) :
                                   0;

                if (processedRenderer != null && processedRenderer.ContainsImage())
                {
                    leadingValue -= previousDescent;
                }
                bool  doesNotFit = result.GetStatus() == LayoutResult.NOTHING;
                float deltaY     = 0;
                if (!doesNotFit)
                {
                    lastLineHeight = processedRenderer.GetOccupiedArea().GetBBox().GetHeight();
                    deltaY         = lastYLine - leadingValue - processedRenderer.GetYLine();
                    // for the first and last line in a paragraph, leading is smaller
                    if (firstLineInBox)
                    {
                        deltaY = -(leadingValue - lastLineHeight) / 2;
                    }
                    doesNotFit = leading != null && processedRenderer.GetOccupiedArea().GetBBox().GetY() + deltaY < layoutBox.
                                 GetY();
                }
                if (doesNotFit)
                {
                    if (currentAreaPos + 1 < areas.Count)
                    {
                        layoutBox      = areas[++currentAreaPos].Clone();
                        lastYLine      = layoutBox.GetY() + layoutBox.GetHeight();
                        firstLineInBox = true;
                    }
                    else
                    {
                        bool keepTogether = IsKeepTogether();
                        if (keepTogether)
                        {
                            return(new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, null == result.GetCauseOfNothing()
                                 ? this : result.GetCauseOfNothing()));
                        }
                        else
                        {
                            ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
                            ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
                            ApplyMargins(occupiedArea.GetBBox(), margins, true);
                            iText.Layout.Renderer.ParagraphRenderer[] split = Split();
                            split[0].lines = lines;
                            foreach (LineRenderer line in lines)
                            {
                                split[0].childRenderers.AddAll(line.GetChildRenderers());
                            }
                            if (processedRenderer != null)
                            {
                                split[1].childRenderers.AddAll(processedRenderer.GetChildRenderers());
                            }
                            if (result.GetOverflowRenderer() != null)
                            {
                                split[1].childRenderers.AddAll(result.GetOverflowRenderer().GetChildRenderers());
                            }
                            if (anythingPlaced)
                            {
                                return(new LayoutResult(LayoutResult.PARTIAL, occupiedArea, split[0], split[1]));
                            }
                            else
                            {
                                if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                                {
                                    occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), currentRenderer.GetOccupiedArea(
                                                                                          ).GetBBox()));
                                    parent.SetProperty(Property.FULL, true);
                                    lines.Add(currentRenderer);
                                    // Force placement of children we have and do not force placement of the others
                                    if (LayoutResult.PARTIAL == result.GetStatus())
                                    {
                                        IRenderer childNotRendered = result.GetCauseOfNothing();
                                        int       firstNotRendered = currentRenderer.childRenderers.IndexOf(childNotRendered);
                                        currentRenderer.childRenderers.RetainAll(currentRenderer.childRenderers.SubList(0, firstNotRendered));
                                        split[1].childRenderers.RemoveAll(split[1].childRenderers.SubList(0, firstNotRendered));
                                        return(new LayoutResult(LayoutResult.PARTIAL, occupiedArea, this, split[1]));
                                    }
                                    else
                                    {
                                        return(new LayoutResult(LayoutResult.FULL, occupiedArea, null, null, this));
                                    }
                                }
                                else
                                {
                                    return(new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, null == result.GetCauseOfNothing()
                                         ? this : result.GetCauseOfNothing()));
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (leading != null)
                    {
                        processedRenderer.Move(0, deltaY);
                        lastYLine = processedRenderer.GetYLine();
                    }
                    occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), processedRenderer.GetOccupiedArea
                                                                          ().GetBBox()));
                    layoutBox.SetHeight(processedRenderer.GetOccupiedArea().GetBBox().GetY() - layoutBox.GetY());
                    lines.Add(processedRenderer);
                    anythingPlaced  = true;
                    firstLineInBox  = false;
                    currentRenderer = (LineRenderer)result.GetOverflowRenderer();
                    previousDescent = processedRenderer.GetMaxDescent();
                }
            }
            if (!isPositioned)
            {
                float moveDown = Math.Min((leadingValue - lastLineHeight) / 2, occupiedArea.GetBBox().GetY() - layoutBox.GetY
                                              ());
                occupiedArea.GetBBox().MoveDown(moveDown);
                occupiedArea.GetBBox().SetHeight(occupiedArea.GetBBox().GetHeight() + moveDown);
            }
            float?blockHeight = this.GetPropertyAsFloat(Property.HEIGHT);

            ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
            if (blockHeight != null && blockHeight > occupiedArea.GetBBox().GetHeight())
            {
                occupiedArea.GetBBox().MoveDown((float)blockHeight - occupiedArea.GetBBox().GetHeight()).SetHeight((float)
                                                                                                                   blockHeight);
                ApplyVerticalAlignment();
            }
            if (isPositioned)
            {
                float y         = (float)this.GetPropertyAsFloat(Property.Y);
                float relativeY = IsFixedLayout() ? 0 : layoutBox.GetY();
                Move(0, relativeY + y - occupiedArea.GetBBox().GetY());
            }
            ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
            ApplyMargins(occupiedArea.GetBBox(), margins, true);
            if (this.GetProperty <float?>(Property.ROTATION_ANGLE) != null)
            {
                ApplyRotationLayout(layoutContext.GetArea().GetBBox().Clone());
                if (IsNotFittingLayoutArea(layoutContext.GetArea()))
                {
                    if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                    {
                        return(new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this));
                    }
                }
            }
            return(new LayoutResult(LayoutResult.FULL, occupiedArea, null, null));
        }
示例#20
0
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            int       pageNumber   = layoutContext.GetArea().GetPageNumber();
            bool      isPositioned = IsPositioned();
            Rectangle parentBBox   = layoutContext.GetArea().GetBBox().Clone();

            if (this.GetProperty <float?>(Property.ROTATION_ANGLE) != null || isPositioned)
            {
                parentBBox.MoveDown(AbstractRenderer.INF - parentBBox.GetHeight()).SetHeight(AbstractRenderer.INF);
            }
            float?blockHeight = RetrieveHeight();

            if (!IsFixedLayout() && blockHeight != null && blockHeight > parentBBox.GetHeight() && !true.Equals(GetPropertyAsBoolean
                                                                                                                    (Property.FORCED_PLACEMENT)))
            {
                return(new LayoutResult(LayoutResult.NOTHING, null, null, this, this));
            }
            float[] margins = GetMargins();
            ApplyMargins(parentBBox, margins, false);
            Border[] borders = GetBorders();
            ApplyBorderBox(parentBBox, borders, false);
            if (isPositioned)
            {
                float x         = (float)this.GetPropertyAsFloat(Property.X);
                float relativeX = IsFixedLayout() ? 0 : parentBBox.GetX();
                parentBBox.SetX(relativeX + x);
            }
            float?blockWidth = RetrieveWidth(parentBBox.GetWidth());

            if (blockWidth != null && (blockWidth < parentBBox.GetWidth() || isPositioned))
            {
                parentBBox.SetWidth((float)blockWidth);
            }
            float[] paddings = GetPaddings();
            ApplyPaddings(parentBBox, paddings, false);
            IList <Rectangle> areas;

            if (isPositioned)
            {
                areas = JavaCollectionsUtil.SingletonList(parentBBox);
            }
            else
            {
                areas = InitElementAreas(new LayoutArea(pageNumber, parentBBox));
            }
            occupiedArea = new LayoutArea(pageNumber, new Rectangle(parentBBox.GetX(), parentBBox.GetY() + parentBBox.
                                                                    GetHeight(), parentBBox.GetWidth(), 0));
            int       currentAreaPos = 0;
            Rectangle layoutBox      = areas[0].Clone();
            // the first renderer (one of childRenderers or their children) to produce LayoutResult.NOTHING
            IRenderer causeOfNothing = null;
            bool      anythingPlaced = false;

            for (int childPos = 0; childPos < childRenderers.Count; childPos++)
            {
                IRenderer    childRenderer = childRenderers[childPos];
                LayoutResult result;
                childRenderer.SetParent(this);
                while ((result = childRenderer.SetParent(this).Layout(new LayoutContext(new LayoutArea(pageNumber, layoutBox
                                                                                                       )))).GetStatus() != LayoutResult.FULL)
                {
                    if (result.GetOccupiedArea() != null)
                    {
                        occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), result.GetOccupiedArea().GetBBox
                                                                              ()));
                        layoutBox.SetHeight(layoutBox.GetHeight() - result.GetOccupiedArea().GetBBox().GetHeight());
                    }
                    if (childRenderer.GetOccupiedArea() != null)
                    {
                        AlignChildHorizontally(childRenderer, layoutBox.GetWidth());
                    }
                    // Save the first renderer to produce LayoutResult.NOTHING
                    if (null == causeOfNothing && null != result.GetCauseOfNothing())
                    {
                        causeOfNothing = result.GetCauseOfNothing();
                    }
                    // have more areas
                    if (currentAreaPos + 1 < areas.Count)
                    {
                        if (result.GetStatus() == LayoutResult.PARTIAL)
                        {
                            childRenderers[childPos] = result.GetSplitRenderer();
                            // TODO linkedList would make it faster
                            childRenderers.Add(childPos + 1, result.GetOverflowRenderer());
                        }
                        else
                        {
                            childRenderers[childPos] = result.GetOverflowRenderer();
                            childPos--;
                        }
                        layoutBox = areas[++currentAreaPos].Clone();
                        break;
                    }
                    else
                    {
                        if (result.GetStatus() == LayoutResult.PARTIAL)
                        {
                            layoutBox.SetHeight(layoutBox.GetHeight() - result.GetOccupiedArea().GetBBox().GetHeight());
                            if (currentAreaPos + 1 == areas.Count)
                            {
                                AbstractRenderer splitRenderer = CreateSplitRenderer(LayoutResult.PARTIAL);
                                splitRenderer.childRenderers = new List <IRenderer>(childRenderers.SubList(0, childPos));
                                splitRenderer.childRenderers.Add(result.GetSplitRenderer());
                                splitRenderer.occupiedArea = occupiedArea;
                                AbstractRenderer overflowRenderer = CreateOverflowRenderer(LayoutResult.PARTIAL);
                                // Apply forced placement only on split renderer
                                overflowRenderer.DeleteOwnProperty(Property.FORCED_PLACEMENT);
                                IList <IRenderer> overflowRendererChildren = new List <IRenderer>();
                                overflowRendererChildren.Add(result.GetOverflowRenderer());
                                overflowRendererChildren.AddAll(childRenderers.SubList(childPos + 1, childRenderers.Count));
                                overflowRenderer.childRenderers = overflowRendererChildren;
                                ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
                                ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
                                ApplyMargins(occupiedArea.GetBBox(), margins, true);
                                return(new LayoutResult(LayoutResult.PARTIAL, occupiedArea, splitRenderer, overflowRenderer, causeOfNothing
                                                        ));
                            }
                            else
                            {
                                childRenderers[childPos] = result.GetSplitRenderer();
                                childRenderers.Add(childPos + 1, result.GetOverflowRenderer());
                                layoutBox = areas[++currentAreaPos].Clone();
                                break;
                            }
                        }
                        else
                        {
                            if (result.GetStatus() == LayoutResult.NOTHING)
                            {
                                bool             keepTogether  = IsKeepTogether();
                                int              layoutResult  = anythingPlaced && !keepTogether ? LayoutResult.PARTIAL : LayoutResult.NOTHING;
                                AbstractRenderer splitRenderer = CreateSplitRenderer(layoutResult);
                                splitRenderer.childRenderers = new List <IRenderer>(childRenderers.SubList(0, childPos));
                                foreach (IRenderer renderer in splitRenderer.childRenderers)
                                {
                                    renderer.SetParent(splitRenderer);
                                }
                                AbstractRenderer  overflowRenderer         = CreateOverflowRenderer(layoutResult);
                                IList <IRenderer> overflowRendererChildren = new List <IRenderer>();
                                overflowRendererChildren.Add(result.GetOverflowRenderer());
                                overflowRendererChildren.AddAll(childRenderers.SubList(childPos + 1, childRenderers.Count));
                                overflowRenderer.childRenderers = overflowRendererChildren;
                                if (keepTogether)
                                {
                                    splitRenderer = null;
                                    overflowRenderer.childRenderers.Clear();
                                    overflowRenderer.childRenderers = new List <IRenderer>(childRenderers);
                                }
                                ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
                                ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
                                ApplyMargins(occupiedArea.GetBBox(), margins, true);
                                if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                                {
                                    return(new LayoutResult(LayoutResult.FULL, occupiedArea, null, null));
                                }
                                else
                                {
                                    return(new LayoutResult(layoutResult, occupiedArea, splitRenderer, overflowRenderer, LayoutResult.NOTHING
                                                            == layoutResult ? result.GetCauseOfNothing() : null));
                                }
                            }
                        }
                    }
                }
                anythingPlaced = true;
                occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), result.GetOccupiedArea().GetBBox
                                                                      ()));
                if (result.GetStatus() == LayoutResult.FULL)
                {
                    layoutBox.SetHeight(layoutBox.GetHeight() - result.GetOccupiedArea().GetBBox().GetHeight());
                    if (childRenderer.GetOccupiedArea() != null)
                    {
                        AlignChildHorizontally(childRenderer, layoutBox.GetWidth());
                    }
                }
                // Save the first renderer to produce LayoutResult.NOTHING
                if (null == causeOfNothing && null != result.GetCauseOfNothing())
                {
                    causeOfNothing = result.GetCauseOfNothing();
                }
            }
            ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
            if (blockHeight != null && blockHeight > occupiedArea.GetBBox().GetHeight())
            {
                occupiedArea.GetBBox().MoveDown((float)blockHeight - occupiedArea.GetBBox().GetHeight()).SetHeight((float)
                                                                                                                   blockHeight);
            }
            if (isPositioned)
            {
                float y         = (float)this.GetPropertyAsFloat(Property.Y);
                float relativeY = IsFixedLayout() ? 0 : layoutBox.GetY();
                Move(0, relativeY + y - occupiedArea.GetBBox().GetY());
            }
            ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
            ApplyMargins(occupiedArea.GetBBox(), margins, true);
            if (this.GetProperty <float?>(Property.ROTATION_ANGLE) != null)
            {
                ApplyRotationLayout(layoutContext.GetArea().GetBBox().Clone());
                if (IsNotFittingLayoutArea(layoutContext.GetArea()))
                {
                    if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)))
                    {
                        return(new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this));
                    }
                }
            }
            ApplyVerticalAlignment();
            return(new LayoutResult(LayoutResult.FULL, occupiedArea, null, null, causeOfNothing));
        }
示例#21
0
 public override LayoutResult Layout(LayoutContext layoutContext)
 {
     return(base.Layout(new LayoutContext(new LayoutArea(layoutContext.GetArea().GetPageNumber(), rect))));
 }