LibrePDF / OpenPDF

OpenPDF is a free Java library for creating and editing PDF files, with a LGPL and MPL open source license. OpenPDF is based on a fork of iText. We welcome contributions from other developers. Please feel free to submit pull-requests and bugreports to this GitHub repository.
Other
3.59k stars 593 forks source link

Table gets rendered differently if put as header or in body content #908

Open migthymax opened 1 year ago

migthymax commented 1 year ago

If the table from my example is written as header it is differently rendered compared to aa written in the body content of the PDF. Here an example code:

import java.io.FileOutputStream;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;

public class TableTest {

    public static void main( final String[] args ) throws Throwable {
        try( final FileOutputStream outputStream = new FileOutputStream( "test.pdf" ) ) {
            final Document pdfDocument = new Document( PageSize.A4 );

            final PdfWriter pdfWriter = PdfWriter.getInstance( pdfDocument,outputStream );
            pdfWriter.setPdfVersion( PdfWriter.VERSION_1_7 );

            final PdfPTable header = new PdfPTable( 5 );
            header.setWidths( new int[] { 30,30,30,30,30 } );
            header.setHeaderRows( 0 );
            header.getDefaultCell().setPadding( 1 );
            header.setSplitLate( false );
            header.setSplitRows( true );

            PdfPCell cell = new PdfPCell( new Phrase( "Gets truncated" ) );
            cell.setColspan( 1 );
            cell.setRowspan( 5 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "Text A" ) );
            cell.setColspan( 1 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setHorizontalAlignment( Element.ALIGN_LEFT );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "Text B" ) );
            cell.setColspan( 2 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "Text C" ) );
            cell.setColspan( 1 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "" ) );
            cell.setColspan( 4 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_TOP );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            Phrase phrase = new Phrase();
            phrase.add( new Phrase( "Text D" ) );
            phrase.add( Chunk.NEWLINE );
            phrase.add( new Phrase( "Text E" ) );
            phrase.add( Chunk.NEWLINE );

            cell = new PdfPCell( phrase );
            cell.setColspan( 3 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "Text F" ) );
            cell.setColspan( 1 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "" ) );
            cell.setColspan( 4 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_TOP );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "Text G" ) );
            cell.setColspan( 1 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
            cell.setHorizontalAlignment( Element.ALIGN_LEFT );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "Text H" ) );
            cell.setColspan( 2 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            phrase = new Phrase();
            phrase.add( new Phrase( "Text I" ) );
            phrase.add( Chunk.NEWLINE );
            phrase.add( new Phrase( "Text J" ) );
            phrase.add( Chunk.NEWLINE );

            cell = new PdfPCell( phrase );
            cell.setColspan( 1 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOX );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            cell = new PdfPCell( new Phrase( "" ) );
            cell.setColspan( 6 );
            cell.setRowspan( 1 );
            cell.setBorder( Rectangle.BOTTOM );
            cell.setPadding( 1 );
            cell.setVerticalAlignment( Element.ALIGN_TOP );
            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
            header.addCell( cell );

            header.setTotalWidth( pdfDocument.right() - pdfDocument.left() );

            final float haederHeight = header.getTotalHeight() * 2f;

            pdfDocument.setMargins( pdfDocument.leftMargin(),pdfDocument.rightMargin(),pdfDocument.left() + haederHeight,pdfDocument.bottomMargin() );

            pdfWriter.setPageEvent( new PdfPageEventHelper() {

                @Override
                public void onEndPage( final PdfWriter writer,final Document document ) {
                    header.writeSelectedRows( 0,-1,pdfDocument.leftMargin(),pdfDocument.top() + haederHeight,writer.getDirectContent() );
                }
            } );

            pdfDocument.open();
            pdfDocument.add( header );
            pdfDocument.close();
        }
    }
}

Here the generated example PDF using the latest master:

test.pdf

asturio commented 8 months ago

Pull requests are welcome.

migthymax commented 8 months ago

I would fix it, and create a PR, but seriously I'm not that deep into PDF file format. I tried to figure it out, but I have no idea where actually start to look, and why the generated PDF is faulty. So any hints?

asturio commented 8 months ago

That's OK. I'm also not sure what is producing this behavior. A table in a header or footer should be rendered the same as in the body. Maybe the problem is the height of the table, which is bigger than the height of the footer/header. And this may break the table.