Switch between ColumnDocumentRenderer and DocumentRenderer in same page?

后端 未结 1 1234
花落未央
花落未央 2021-01-24 22:00

I was testing few things with iText7 and I have a scenario where I need to have DocumentRenderer paragraph at the top and then start the ColumnDocumentRender with 2 columns righ

1条回答
  •  北海茫月
    2021-01-24 22:19

    I have taken this code: C02E08_JekyllHydeV4

    And I updated it according to what you have in your question:

    //Initialize PDF document
    PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
    // Initialize document
    Document document = new Document(pdf);
    Paragraph p = new Paragraph()
        .add("Be prepared to read a story about a London lawyer "
           + "named Gabriel John Utterson who investigates strange "
           + "occurrences between his old friend, Dr. Henry Jekyll, "
           + "and the evil Edward Hyde.");
    document.add(p);
    document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
    
    //Set column parameters
    ...
    //Define column areas
    ...
    document.setRenderer(new ColumnDocumentRenderer(document, columns)); 
    document.add(new AreaBreak(AreaBreakType.LAST_PAGE));   
    // Add the full Jekyl and Hyde text
    document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
    document.setRenderer(new DocumentRenderer(document)); 
    document.add(new AreaBreak(AreaBreakType.LAST_PAGE));
    p = new Paragraph()
        .add("This was the story about the London lawyer "
           + "named Gabriel John Utterson who investigates strange "
           + "occurrences between his old friend, Dr. Henry Jekyll, "
           + "and the evil Edward Hyde. THE END!");
    document.add(p);
    //Close document
    document.close();
    

    The result looks like this:

    I think that's the behavior you are looking for. If it's not, please explain what goes wrong.

    UPDATE:

    After clarifying the question, it is clear that the above answer doesn't solve the problem. This is the solution to the actual problem:

    We need to create a custom ParagraphRenderer to determine a Y-position: class MyParagraphRenderer extends ParagraphRenderer {

        float y;
    
        public MyParagraphRenderer(Paragraph modelElement) {
            super(modelElement);
        }
    
        @Override
        public void drawBorder(DrawContext drawContext) {
            super.drawBorder(drawContext);
            y = getOccupiedAreaBBox().getBottom();
        }
    
        public float getY() {
            return y;
        }
    
    }
    

    When we add the first paragraph, we need to use this custom ParagraphRenderer:

    Paragraph p = new Paragraph()
            .add("Be prepared to read a story about a London lawyer "
            + "named Gabriel John Utterson who investigates strange "
            + "occurrences between his old friend, Dr. Henry Jekyll, "
            + "and the evil Edward Hyde.");
    MyParagraphRenderer renderer = new MyParagraphRenderer(p);
    p.setNextRenderer(renderer);
    document.add(p);
    

    We can now get the Y position we need like this: renderer.getY(); we use this Y position to define a first set of columns:

    float offSet = 36;
    float gutter = 23;
    float columnWidth = (PageSize.A4.getWidth() - offSet * 2) / 2 - gutter;
    float columnHeight1 = renderer.getY() - offSet * 2;
    Rectangle[] columns1 = {
        new Rectangle(offSet, offSet, columnWidth, columnHeight1),
        new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight1)};
    

    We could use this set of columns to create a ColumnDocumentRenderer, but if more than one page is needed to render all the content, then the offset of the columns on the second page will be wrong, hence we also create a custom ColumnDocumentRenderer:

    class MyColumnDocumentRenderer extends ColumnDocumentRenderer {
    
        Rectangle[] columns2;
    
        public MyColumnDocumentRenderer(Document document, Rectangle[] columns1, Rectangle[] columns2) {
            super(document, columns1);
            this.columns2 = columns2;
        }
    
        @Override
        protected PageSize addNewPage(PageSize customPageSize) {
            PageSize size = super.addNewPage(customPageSize);
            columns = columns2;
            return size;
        }
    }
    

    This ColumnDocumentRenderer accepts two sets of columns, one set will be used on the first page, the second set will be used on all subsequent pages. This is how we define and apply the custom ColumnDocumentRenderer:

    float columnHeight2 = PageSize.A4.getHeight() - offSet * 2;
    Rectangle[] columns2 = {
        new Rectangle(offSet, offSet, columnWidth, columnHeight2),
        new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight2)};
    document.setRenderer(new MyColumnDocumentRenderer(document, columns1, columns2));  
    

    Now the result looks like this:

    Depending on the distance you want between the first page-wide paragraph and the subsequent content in the columns, you can adjust the value of renderer.getY() - offSet * 2.

    0 讨论(0)
提交回复
热议问题