使用 iText7 在页面上移动文本,保留字体、颜色、样式......但改变文本的大小

Moving text on a page with iText7 retaining font, color, style, ... but changing size of the text

我想用 iText7 移动文本。我有一个源边界框,它可以位于页面上的某个位置,我有一个目标边界框,它有一个固定的位置(包括宽度和高度)。我会保持一致。源框和目标框可以重叠。源边界框也可以比目标框大。在这种情况下,我必须减小字体大小。文字要保留字体、颜色等。

iText 网站上有 cut and paste example。但在结果 pdf 文件中,您可以 select 新旧位置的文本(仅使用普通 pdf reader 尝试过)。我不希望文本 select 能够显示在旧位置。

我想,也许我可以 select 将文本放在新位置并将其从旧位置删除。对于后者,我需要 pdfSweep,但这没关系。在新位置添加文本应该没有问题。即使文本具有不同的字体、大小等。 iText 网站上有很多示例。我知道 select 文本的唯一方法就像 example 中所示。这只给我文字。但是要以相同的字体、颜色等将其放置在目标位置,我也需要所有这些信息。 我知道,pdf 不适合编辑。 Whosebug 上的答案中经常提到这一点。 有没有办法用 iText7 做到这一点?

iText 中没有高级 API 允许您移动 页面内容,尤其是来自某个矩形的所有内容[=25] =].原因之一可能是,一般来说,这不仅仅是移动。 PDF 通常包含影响更大区域的结构,并且此类结构不仅需要简单地移动,还需要复制,并且每个副本都限制在其区域。

不过,确实有可能将 cut and paste example OP 与 pdfSweep 模块找到的 OP 已经考虑过的解决方案结合起来,以防止 在旧版本中可选择文本位置, 例如像这样:

public void moveCleanSection(PdfReader pdfReader, String targetFile, int page, Rectangle from, Rectangle to) throws IOException
{
    LicenseKey.loadLicenseFile("itextkey-multiple-products.xml");

    ByteArrayOutputStream interimMain = new ByteArrayOutputStream();
    ByteArrayOutputStream interimPage = new ByteArrayOutputStream();
    ByteArrayOutputStream interimSection = new ByteArrayOutputStream();

    try (   PdfDocument pdfMainDocument = new PdfDocument(pdfReader);
            PdfDocument pdfPageDocument = new PdfDocument(new PdfWriter(interimPage)) )
    {
        pdfMainDocument.setCloseReader(false);
        pdfMainDocument.copyPagesTo(page, page, pdfPageDocument);
    }

    try (   PdfDocument pdfMainDocument = new PdfDocument(pdfReader, new PdfWriter(interimMain));
            PdfDocument pdfSectionDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(interimPage.toByteArray())), 
            new PdfWriter(interimSection))  )
    {

        List<PdfCleanUpLocation> cleanUpLocations = new ArrayList<PdfCleanUpLocation>();
        cleanUpLocations.add(new PdfCleanUpLocation(page, from, null));
        cleanUpLocations.add(new PdfCleanUpLocation(page, to, null));

        PdfCleanUpTool cleaner = new PdfCleanUpTool(pdfMainDocument, cleanUpLocations);
        cleaner.cleanUp();

        cleanUpLocations = new ArrayList<PdfCleanUpLocation>();
        Rectangle mediaBox = pdfSectionDocument.getPage(1).getMediaBox();

        if (from.getTop() < mediaBox.getTop())
            cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(mediaBox.getLeft(), from.getTop(), mediaBox.getWidth(), mediaBox.getTop() - from.getTop()), null));
        if (from.getBottom() > mediaBox.getBottom())
            cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(mediaBox.getLeft(), mediaBox.getBottom(), mediaBox.getWidth(), from.getBottom() -  mediaBox.getBottom()), null));
        if (from.getLeft() > mediaBox.getLeft())
            cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(mediaBox.getLeft(), mediaBox.getBottom(), from.getLeft() - mediaBox.getLeft(), mediaBox.getHeight()), null));
        if (from.getRight() < mediaBox.getRight())
            cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(from.getRight(), mediaBox.getBottom(), mediaBox.getRight() - from.getRight(), mediaBox.getHeight()), null));

        cleaner = new PdfCleanUpTool(pdfSectionDocument, cleanUpLocations);
        cleaner.cleanUp();
    }

    try (   PdfDocument pdfSectionDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(interimSection.toByteArray())));
            PdfDocument pdfMainDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(interimMain.toByteArray())), new PdfWriter(targetFile)) )
    {
        float scale = Math.min(to.getHeight() / from.getHeight(), to.getWidth() / from.getWidth());
        pdfSectionDocument.getPage(1).setMediaBox(from);
        PdfFormXObject pageXObject = pdfSectionDocument.getFirstPage().copyAsFormXObject(pdfMainDocument);
        PdfPage pdfPage = pdfMainDocument.getPage(page);
        PdfCanvas pdfCanvas = new PdfCanvas(pdfPage);
        pdfCanvas.addXObject(pageXObject, scale, 0, 0, scale, (to.getLeft() - from.getLeft() * scale), (to.getBottom() - from.getBottom() * scale));
    }
}

(来自MoveSectionCleanly.java

注意:由于 pdfSweep 的性质,源区域边界上的文本将从源及其副本中删除。