How can i add source PDF content to destination PDF using IText7 without losing Header and Footer?

前端 未结 1 1432
夕颜
夕颜 2021-01-25 02:18

I am using Itext 7. I have two PDF\'s. The source PDF has some content. The destination PDF has header and footer. I have a requirement to add the content from source PDF to des

相关标签:
1条回答
  • 2021-01-25 02:50

    First off, some words on the iText architecture behind some constructs you use:

    When you use a Document instance to add content to a document that iText shall layout automatically, the assumption is that the area where iText can layout stuff is the whole page minus the page margins.

    Thus, if you add further page material via other channels than the Document, e.g. like you do in your NormalPageHeader headerHandler and your PageEndEvent pageEndEvent, it is your responsibility to do so outside the layout area explained above, i.e. in the margin areas. (Unless that additional material is background stuff, like a water sign...)

    For this you should set the margins large enough to guarantee that your further material is in the margins. By default the page margins are set to 36pt on each side of the page which usually is enough for a single line header or footer but not really for multi-line ones.

    In your code you create a header which requires at least some 52pt plus a bit to prevent the content iText will layout from touching the header line.

    Keeping that in mind it is pretty straight forward to insert a given PdfPage sourcePage into your page:

    ...
    NormalPageHeader headerHandler = testPdf.new NormalPageHeader(Paths.get("images").toAbsolutePath() + "\\logo.png", pdfFontMap);
    pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);
    PageEndEvent pageEndEvent = testPdf.new PageEndEvent(Paths.get("images").toAbsolutePath() + "\\FooterLineExternal.png" ,pdfFontMap);
    pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, pageEndEvent);
    
    Document doc = new Document(pdfDoc);
    doc.setTopMargin(55);
    PdfFormXObject xobject = sourcePage.copyAsFormXObject(pdfDoc);
    Rectangle xobjectBoundaryBox = xobject.getBBox().toRectangle();
    xobject.getPdfObject().put(PdfName.Matrix, new PdfArray(new float[] {1, 0, 0, 1, -xobjectBoundaryBox.getLeft(), -xobjectBoundaryBox.getBottom()}));
    Image image = new Image(xobject);
    image.setAutoScale(true);
    doc.add(image);
    
    doc.close();
    ...
    

    (excerpt from InsertInSpace helper insertIntoNithinTestFile)


    If you use the original source page as is, the above code will insert it including all margin space. If you don't want this but instead cut that space of, you can proceed as follows to determine the actual bounding box of the page content, reduce the page to that box, and forward it to the method insertIntoNithinTestFile above, assuming page 1 of PdfDocument pdfDocument shall be processed:

    PdfDocumentContentParser contentParser = new PdfDocumentContentParser(pdfDocument);
    MarginFinder strategy = contentParser.processContent(1, new MarginFinder());
    
    PdfPage page = pdfDocument.getPage(1);
    page.setCropBox(strategy.getBoundingBox());
    page.setMediaBox(strategy.getBoundingBox());
    insertIntoNithinTestFile(page, "test-InsertIntoNithinTestFile.pdf");
    

    (InsertInSpace test testInsertSimpleTestPdf)

    The MarginFinder is a port of the iText5 MarginFinder to iText 7:

    public class MarginFinder implements IEventListener {
        public Rectangle getBoundingBox() {
            return boundingBox != null ? boundingBox.clone() : null;
        }
    
        @Override
        public void eventOccurred(IEventData data, EventType type) {
            if (data instanceof ImageRenderInfo) {
                ImageRenderInfo imageData = (ImageRenderInfo) data;
                Matrix ctm = imageData.getImageCtm();
                for (Vector unitCorner : UNIT_SQUARE_CORNERS) {
                    Vector corner = unitCorner.cross(ctm);
                    addToBoundingBox(new Rectangle(corner.get(Vector.I1), corner.get(Vector.I2), 0, 0));
                }
            } else if (data instanceof TextRenderInfo) {
                TextRenderInfo textRenderInfo = (TextRenderInfo) data;
                addToBoundingBox(textRenderInfo.getAscentLine().getBoundingRectangle());
                addToBoundingBox(textRenderInfo.getDescentLine().getBoundingRectangle());
            } else if (data instanceof PathRenderInfo) {
                PathRenderInfo renderInfo = (PathRenderInfo) data;
                if (renderInfo.getOperation() != PathRenderInfo.NO_OP)
                {
                    Matrix ctm = renderInfo.getCtm();
                    Path path = renderInfo.getPath();
                    for (Subpath subpath : path.getSubpaths())
                    {
                        for (Point point2d : subpath.getPiecewiseLinearApproximation())
                        {
                            Vector vector = new Vector((float)point2d.getX(), (float)point2d.getY(), 1);
                            vector = vector.cross(ctm);
                            addToBoundingBox(new Rectangle(vector.get(Vector.I1), vector.get(Vector.I2), 0, 0));
                        }
                    }
                }
            } else if (data != null) {
                logger.fine(String.format("Ignored %s event, class %s.", type, data.getClass().getSimpleName()));
            } else {
                logger.fine(String.format("Ignored %s event with null data.", type));
            }
        }
    
        @Override
        public Set<EventType> getSupportedEvents() {
            return null;
        }
    
        void addToBoundingBox(Rectangle rectangle) {
            if (boundingBox == null)
                boundingBox = rectangle.clone();
            else
                boundingBox = Rectangle.getCommonRectangle(boundingBox, rectangle);
        }
    
        Rectangle boundingBox = null;
        Logger logger = Logger.getLogger(MarginFinder.class.getName());
        static List<Vector> UNIT_SQUARE_CORNERS = Arrays.asList(new Vector(0,0,1), new Vector(1,0,1), new Vector(1,1,1), new Vector(0,1,1));
    }
    

    (MarginFinder.java)

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