2016-01-26 69 views
2

我正在嘗試開發支持i18n和多行水印的水印壓印。我可以創建它,但問題是水印與前一行的文本重疊,如下圖所示。 enter image description here多行水印重疊問題

我的水印文本包含以下內容: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中所述)。

回答

0

基於mkl's answerPaulo's answer我可以注意到我的微積分存在一些錯誤。下面是現在的工作,我的代碼:

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); 
} 
0

看起來像Paragraph領先是不夠的。設置與字體相同的尺寸或1.25,以獲得令人愉快的印刷效果。

0

您計算currentLineHeight總和AscentDescent

final float currentLineHeight = c.getFont().getBaseFont().getAscentPoint(lines[indexer], fontSize) + c.getFont().getBaseFont().getDescentPoint(lines[indexer], fontSize); 

Descent並不積極,但爲零甚至是負數,比照JavaDoc中:

/** 
* Gets the descent of a <CODE>String</CODE> in points. The descent will always be 
* less than or equal to zero even if all the characters have an higher descent. 
* @param text the <CODE>String</CODE> to get the descent of 
* @param fontSize the size of the font 
* @return the descent in points 
*/ 
public float getDescentPoint(String text, float fontSize) 

因此,最有可能你需要的差異這裏(或絕對值之和):

final float currentLineHeight = c.getFont().getBaseFont().getAscentPoint(lines[indexer], fontSize) - c.getFont().getBaseFont().getDescentPoint(lines[indexer], fontSize); 

(這至少將正確計算矩形,特別是當您開始創建帶有相關下降字符的水印時)。