All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.itextpdf.text.pdf.FloatLayout Maven / Gradle / Ivy

There is a newer version: 5.5.13.3
Show newest version
/*
 * $Id: FloatLayout.java 5914 2013-07-28 14:18:11Z blowagie $
 *
 * This file is part of the iText (R) project.
 * Copyright (c) 1998-2013 1T3XT BVBA
 * Authors: Bruno Lowagie, Paulo Soares, et al.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation with the addition of the
 * following permission added to Section 15 as permitted in Section 7(a):
 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
 * http://itextpdf.com/terms-of-use/
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License,
 * a covered work must retain the producer line in every PDF that is created
 * or manipulated using iText.
 *
 * You can be released from the requirements of the license by purchasing
 * a commercial license. Buying such a license is mandatory as soon as you
 * develop commercial activities involving the iText software without
 * disclosing the source code of your own applications.
 * These activities include: offering paid services to customers as an ASP,
 * serving PDFs on the fly in a web application, shipping iText with a closed
 * source product.
 *
 * For more information, please contact iText Software Corp. at this
 * address: [email protected]
 */
package com.itextpdf.text.pdf;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.api.Spaceable;

import java.util.ArrayList;
import java.util.List;

/**
 * Helper class for PdfDiv to put a collection of Element objects
 * at an absolute position.
 */
public class FloatLayout {
    protected float maxY;

    protected float minY;

    protected float leftX;

    protected float rightX;

    public float getYLine() {
        return yLine;
    }

    public void setYLine(float yLine) {
        this.yLine = yLine;
    }

    protected float yLine;

    protected float floatLeftX;

    protected float floatRightX;

    public float getFilledWidth() {
        return filledWidth;
    }

    public void setFilledWidth(float filledWidth) {
        this.filledWidth = filledWidth;
    }

    protected float filledWidth;

    protected final ColumnText compositeColumn;

    protected final List content;

    protected final boolean useAscender;

    public FloatLayout(List elements, boolean useAscender) {
        compositeColumn = new ColumnText(null);
        compositeColumn.setUseAscender(useAscender);
        this.useAscender = useAscender;
        content = elements;
    }

    public void setSimpleColumn(final float llx, final float lly, final float urx, final float ury) {
        leftX = Math.min(llx, urx);
        maxY = Math.max(lly, ury);
        minY = Math.min(lly, ury);
        rightX = Math.max(llx, urx);
        floatLeftX = leftX;
        floatRightX = rightX;
        yLine = maxY;
        filledWidth = 0;
    }

    public int layout(PdfContentByte canvas, boolean simulate)  throws DocumentException  {
        compositeColumn.setCanvas(canvas);
        int status = ColumnText.NO_MORE_TEXT;
        filledWidth = 0;

        ArrayList floatingElements = new ArrayList();
        List content = simulate ? new ArrayList(this.content) : this.content;

        while (!content.isEmpty()) {
            if (content.get(0) instanceof PdfDiv) {
                PdfDiv floatingElement = (PdfDiv)content.get(0);
                if (floatingElement.getFloatType() == PdfDiv.FloatType.LEFT || floatingElement.getFloatType() == PdfDiv.FloatType.RIGHT) {
                    floatingElements.add(floatingElement);
                    content.remove(0);
                } else {
                    if (!floatingElements.isEmpty()) {
                        status = floatingLayout(floatingElements, simulate);
                        if ((status & ColumnText.NO_MORE_TEXT) == 0) {
                            break;
                        }
                    }

                    content.remove(0);

                    status = floatingElement.layout(canvas, useAscender, true, floatLeftX, minY, floatRightX, yLine);

                    if (!simulate) {
                        canvas.openMCBlock(floatingElement);
                        status = floatingElement.layout(canvas, useAscender, simulate, floatLeftX, minY, floatRightX, yLine);
                        canvas.closeMCBlock(floatingElement);
                    }

                    yLine -= floatingElement.getActualHeight();

                    if (floatingElement.getActualWidth() > filledWidth) {
                        filledWidth = floatingElement.getActualWidth();
                    }
                    if ((status & ColumnText.NO_MORE_TEXT) == 0) {
                        content.add(0, floatingElement);
                        break;
                    }
                }
            } else {
                floatingElements.add(content.get(0));
                content.remove(0);
            }
        }

        if ((status & ColumnText.NO_MORE_TEXT) != 0 && !floatingElements.isEmpty()) {
            status = floatingLayout(floatingElements, simulate);
        }

        content.addAll(0, floatingElements);

        return status;
    }

    private int floatingLayout(List floatingElements, boolean simulate) throws DocumentException {
        int status = ColumnText.NO_MORE_TEXT;
        float minYLine = yLine;
        float leftWidth = 0;
        float rightWidth = 0;

        ColumnText currentCompositeColumn = compositeColumn;
        if (simulate) {
            currentCompositeColumn = ColumnText.duplicate(compositeColumn);
        }

        while (!floatingElements.isEmpty()) {
            Element nextElement = floatingElements.get(0);
            floatingElements.remove(0);
            if (nextElement instanceof PdfDiv) {
                PdfDiv floatingElement = (PdfDiv) nextElement;
                status = floatingElement.layout(compositeColumn.getCanvas(), useAscender, true, floatLeftX, minY, floatRightX, yLine);
                if ((status & ColumnText.NO_MORE_TEXT) == 0) {
                    yLine = minYLine;
                    floatLeftX = leftX;
                    floatRightX = rightX;
                    status = floatingElement.layout(compositeColumn.getCanvas(), useAscender, true, floatLeftX, minY, floatRightX, yLine);
                    if ((status & ColumnText.NO_MORE_TEXT) == 0) {
                        floatingElements.add(0, floatingElement);
                        break;
                    }
                }
                if (floatingElement.getFloatType() == PdfDiv.FloatType.LEFT) {
                    status = floatingElement.layout(compositeColumn.getCanvas(), useAscender, simulate, floatLeftX, minY, floatRightX, yLine);
                    floatLeftX += floatingElement.getActualWidth();
                    leftWidth += floatingElement.getActualWidth();
                } else if (floatingElement.getFloatType() == PdfDiv.FloatType.RIGHT) {
                    status = floatingElement.layout(compositeColumn.getCanvas(), useAscender, simulate, floatRightX - floatingElement.getActualWidth() - 0.01f, minY, floatRightX, yLine);
                    floatRightX -= floatingElement.getActualWidth();
                    rightWidth += floatingElement.getActualWidth();
                }
                minYLine = Math.min(minYLine, yLine - floatingElement.getActualHeight());
            } else {
                if (nextElement instanceof Spaceable) {
                    yLine -= ((Spaceable) nextElement).getSpacingBefore();
                }
                if (simulate) {
                    if (nextElement instanceof PdfPTable)
                        currentCompositeColumn.addElement(new PdfPTable((PdfPTable)nextElement));
                    else
                        currentCompositeColumn.addElement(nextElement);
                } else {
                    currentCompositeColumn.addElement(nextElement);
                }

                if (yLine > minYLine)
                    currentCompositeColumn.setSimpleColumn(floatLeftX, yLine, floatRightX, minYLine);
                else
                    currentCompositeColumn.setSimpleColumn(floatLeftX, yLine, floatRightX, minY);

                currentCompositeColumn.setFilledWidth(0);

                status = currentCompositeColumn.go(simulate);
                if (yLine > minYLine && (floatLeftX > leftX || floatRightX < rightX) && (status & ColumnText.NO_MORE_TEXT) == 0) {
                    yLine = minYLine;
                    floatLeftX = leftX;
                    floatRightX = rightX;
                    if (leftWidth != 0 && rightWidth != 0) {
                        filledWidth = rightX - leftX;
                    } else {
                        if (leftWidth > filledWidth) {
                            filledWidth = leftWidth;
                        }
                        if (rightWidth > filledWidth) {
                            filledWidth = rightWidth;
                        }
                    }

                    leftWidth = 0;
                    rightWidth = 0;
                    if (simulate && nextElement instanceof PdfPTable) {
                        currentCompositeColumn.addElement(new PdfPTable((PdfPTable)nextElement));
                    }

                    currentCompositeColumn.setSimpleColumn(floatLeftX, yLine, floatRightX, minY);
                    status = currentCompositeColumn.go(simulate);
                    minYLine = currentCompositeColumn.getYLine() + currentCompositeColumn.getDescender();
                    yLine = minYLine;
                    if (currentCompositeColumn.getFilledWidth() > filledWidth) {
                        filledWidth = currentCompositeColumn.getFilledWidth();
                    }
                } else {
                    if (rightWidth > 0) {
                        rightWidth += currentCompositeColumn.getFilledWidth();
                    } else if (leftWidth > 0) {
                        leftWidth += currentCompositeColumn.getFilledWidth();
                    } else if (currentCompositeColumn.getFilledWidth() > filledWidth) {
                        filledWidth = currentCompositeColumn.getFilledWidth();
                    }
                    minYLine = Math.min(currentCompositeColumn.getYLine() + currentCompositeColumn.getDescender(), minYLine);
                    yLine = currentCompositeColumn.getYLine() + currentCompositeColumn.getDescender();
                }

                if ((status & ColumnText.NO_MORE_TEXT) == 0) {
                    if (!simulate) {
                        floatingElements.addAll(0, currentCompositeColumn.getCompositeElements());
                        currentCompositeColumn.getCompositeElements().clear();
                    } else {
                        floatingElements.add(0, nextElement);
                        currentCompositeColumn.setText(null);
                    }
                    break;
                } else {
                    currentCompositeColumn.setText(null);
                }
            }
        }


        if (leftWidth != 0 && rightWidth != 0) {
            filledWidth = rightX - leftX;
        } else {
            if (leftWidth > filledWidth) {
                filledWidth = leftWidth;
            }
            if (rightWidth > filledWidth) {
                filledWidth = rightWidth;
            }
        }

        yLine = minYLine;
        floatLeftX = leftX;
        floatRightX = rightX;

        return status;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy