程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

多行水印重叠问题

发布于2022-05-01 18:08     阅读(1392)     评论(0)     点赞(20)     收藏(5)


我正在尝试开发一种支持 i18n 和多行水印的水印压模。我可以创建它,但问题是水印与上一行的文本重叠,如下图所示。在此处输入图像描述

我的水印文字有以下内容:123\n456\n789. 我愿意做的是在不重叠线条的情况下设置水印。我怎样才能做到这一点?以下是我的部分代码:

WaterMarkStamper.java

public void insertWaterMark() throws Exception {
    final File pdfFile = this.getFile();
    if (pdfFile != null && pdfFile.exists()) {
        PdfReader reader = null;
        PdfStamper stamp = null;
        try {
            reader = new PdfReader(pdfFile.getAbsolutePath());
            final int n = reader.getNumberOfPages();
            temp = this.getNewFile();
            // Create a stamper that will copy the document to a new file
            stamp = new PdfStamper(reader, new FileOutputStream(temp));
            PdfContentByte over;
            int pageIndex = 1;
            while (pageIndex <= n) {
                over = stamp.getOverContent(pageIndex);
                this.addWatermark(wmVO, reader, over, pageIndex, position);
                pageIndex++;
            }
        } catch (final Exception e) {
            WaterMarkStamper.logger.error(e.getMessage(), e);
        } finally {
            if (stamp != null) {
                stamp.close();
            }
            if (reader != null) {
                reader.close();
            }
        }
    }
}

private void addWatermark(final WaterMarkVO wmVo, final PdfReader reader, final PdfContentByte contentByte, final Integer pageIndex) throws Exception {
    final Rectangle page = reader.getPageSizeWithRotation(pageIndex);

    // This is where the magic happens
    final Image img = wmVo.getImage(contentByte);

    // Get margins
    final int leftMargin = wmVo.getLeftMargin();
    final int topMargin = wmVo.getTopMargin();
    final int rightMargin = wmVo.getRightMargin();
    final int bottomMargin = wmVo.getBottomMargin();

    // Absolute position
    final Point pt = this.getImageInsertionPoint(img, page, leftMargin, topMargin, rightMargin, bottomMargin);
    img.setAbsolutePosition((float) pt.getX(), (float) pt.getY());

    // Add image
    contentByte.addImage(img);
}

WaterMarkVO.java

public Image getImage(final PdfContentByte contentByte) throws Exception {
    final Paragraph paragraph = this.getParagraph();
    final Rectangle paragraphRectangle = this.getParagraphRectangle();
    final float paragraphHeight = paragraphRectangle.getHeight();
    final float paragraphWidth = paragraphRectangle.getWidth();

    final PdfTemplate xObject = contentByte.createTemplate(paragraphWidth, paragraphHeight + this.getFontSize());
    final ColumnText column = new ColumnText(xObject);
    column.setSimpleColumn(0, 0, paragraphWidth, paragraphHeight);
    column.setExtraParagraphSpace(0f);
    column.addElement(paragraph);
    column.go();

    final Image img = Image.getInstance(xObject);
    final int rotation = this.getRotation();
    img.setRotationDegrees(rotation);
    return img;
}

public Paragraph getParagraph() throws Exception {
    final FontSelector fontSelector = this.getFontSelector();
    final String text = "123\n456\n789";
    this.fontSelectorPhrase = fontSelector.process(text);
    final Paragraph paragraph = new Paragraph(this.fontSelectorPhrase);

    return paragraph;
}

public Rectangle getParagraphRectangle() throws Exception {
    final String text = "123\n456\n789";
    final float fontSize = this.getFontSize();
    float paragraphWidth = 0f;
    float paragraphHeight = 0f;
    float leading = 0f;
    final String[] lines = text.split("\n");

    List<Chunk> chunks = this.fontSelectorPhrase.getChunks();
    for(Chunk c : chunks) {
        int indexer = 0;
        final Paragraph p = new Paragraph(" ", c.getFont());
        do {
            final float currentLineWidth = c.getFont().getBaseFont().getWidthPoint(" " + lines[indexer] + " ", fontSize);
            final float currentLineHeight = c.getFont().getBaseFont().getAscentPoint(lines[indexer], fontSize) + c.getFont().getBaseFont().getDescentPoint(lines[indexer], fontSize);
            final float curentLineLeading = p.getLeading();

            paragraphWidth = currentLineWidth > paragraphWidth ? currentLineWidth : paragraphWidth;
            paragraphHeight = currentLineHeight > paragraphHeight ? currentLineHeight : paragraphHeight;
            leading = currentLineLeading > leading ? currentLineLeading : leading; 
            indexer++;
        } while (indexer < lines.length);
    }

    paragraphHeight += leading / lines.length;

    return new Rectangle(paragraphWidth, paragraphHeight);
}

public FontSelector getFontSelector() throws Exception {
    // Adding fonts to support i18n
    FontSelector fontSelector = new FontSelector();
    fontSelector.addFont(new Font(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED))); // Does not support some turkish glyphs 
    fontSelector.addFont(new Font(BaseFont.createFont("helvetica.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED))); // Support some turkish glyphs
    return fontSelector;
}

显然,我隐藏了部分不必要的代码。在此示例中,我没有在水印上使用特殊字符,但我的代码必须满足此要求(我遵循了“iText in Action 2nd edition”中 p378 中所述的内容)。


解决方案


根据mkl 的回答Paulo 的回答,我可以注意到我的微积分中的一些错误。下面是现在为我工作的代码:

WaterMarkVO.java

public Image getImage(final PdfContentByte contentByte) throws Exception {
    final Paragraph paragraph = this.getParagraph();
    final Rectangle paragraphRectangle = this.getParagraphRectangle();
    final float paragraphHeight = paragraphRectangle.getHeight();
    final float paragraphWidth = paragraphRectangle.getWidth();

    final PdfTemplate xObject = contentByte.createTemplate(paragraphWidth, paragraphHeight + this.getFontSize());
    final ColumnText column = new ColumnText(xObject);
    column.setSimpleColumn(0, 0, paragraphWidth, paragraphHeight);
    column.setExtraParagraphSpace(0f);
    column.addElement(paragraph);
    column.go();

    final Image img = Image.getInstance(xObject);
    final int rotation = this.getRotation();
    img.setRotationDegrees(rotation);
    return img;
}

public Rectangle getParagraphRectangle(final WatermarkPosition position, Paragraph para) throws Exception {
    int numberOfLines = 1;
    float paragraphWidth = 0f;
    float paragraphHeight = 0f;
    float leading = 0f;
    float chunkFontSize = 0f;
    float currentChunkWidth = 0f;
    float currentChunkHeight = 0f;
    Font f = null;
    BaseFont bf = null;
    String content = null;

    List<Chunk> chunks = this.fontSelectorPhrase.getChunks();
    for(Chunk c : chunks) {
        f = c.getFont();
        bf = f.getBaseFont();
        content = c.getContent();
        chunkFontSize = f.getSize();
        currentChunkWidth = bf.getWidthPoint(" " + content + " ", chunkFontSize);

        currentChunkHeight = chunkFontSize + bf.getAscentPoint(content, chunkFontSize) - bf.getDescentPoint(content, chunkFontSize);

        if(!c.getContent().contains(System.getProperty("line.separator"))) {
            paragraphWidth += currentChunkWidth > paragraphWidth ? currentChunkWidth : paragraphWidth;
        } else {
            paragraphWidth = currentChunkWidth;
            numberOfLines++;
        }

        paragraphHeight = currentChunkHeight > paragraphHeight ? currentChunkHeight : paragraphHeight;

        leading = chunkFontSize > leading ? chunkFontSize : leading; 
    }

    para.setLeading(leading);

    paragraphHeight += (leading * numberOfLines);

    return new Rectangle(paragraphWidth, paragraphHeight);
}


所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:http://www.javaheidong.com/blog/article/437993/d285a1e23fcb6d54a76d/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

20 0
收藏该文
已收藏

评论内容:(最多支持255个字符)