首页 > 解决方案 > 在 PDFBOX 中围绕字符绘制边界框

问题描述

我想为我绘制到 pdf 的每个字符计算边界框,用于一堆不同的字体和大小。对于不同的字体,它似乎有不同的工作方式,例如 arial mt 与常规的大象。

例如,我一直在使用 - 符号来感受这一点,在 Arial 中,左下角是 65,440,大象是 7,165,但大象被画得更高,我找不到这个动作的来源。

大多数字体的工作方式更像 Arial,字体的顶部为 height/2,但这不适用于大象字体。

准确计算边界框需要包括哪些因素?

package com.nexiaem.nemocr.generatepdf;

import java.awt.Color;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
import org.apache.pdfbox.util.Vector;

/**
 *
 * @author bjames
 */
public class DrawBoundngBox {
    public static void main(String[] args){
        try{

            PDPage thisPage = new PDPage(new PDRectangle(100, 40));
            PDDocument document = new PDDocument();
            document.addPage(thisPage);
            //PDTrueTypeFont font = PDTrueTypeFont.loadTTF(document, new File("C:\\windows\\fonts\\elephnt.ttf"));
            PDTrueTypeFont font = PDTrueTypeFont.loadTTF(document, new File("C:\\windows\\fonts\\arial.ttf"));
            PDPageContentStream contentStream = new PDPageContentStream(document, thisPage);

            int thisSize = 10;
            float currentX = 0;                  
            float width = 0;
            String charactersToWrite = "aj";
            char[] characters = charactersToWrite.toCharArray();
            for(char thisChar: characters){
                String thisCharString = Character.toString(thisChar);
                width = (font.getWidthFromFont((int)thisChar) / 1000.0f) * thisSize;
                GeneralPath charPath = font.getPath((int)thisChar);
                Rectangle2D charRect = charPath.getBounds2D();
                float charMinX = thisSize * (float)charRect.getMinX() / 1000.0f;
                float charMaxX = thisSize * (float)charRect.getMaxX() / 1000.0f;
                float charMinY = thisSize * (float)charRect.getMinY() / 1000.0f;
                float charX = thisSize * (float)charRect.getX() / 1000.0f;
                float charY = thisSize * (float)charRect.getY() / 1000.0f;
                Vector displacement = font.getDisplacement((int)thisChar);
                float charWidth = thisSize * (float)charRect.getWidth()/ 1000.0f;
                width = charMaxX - charMinX;

                float height = ((float)charRect.getHeight()/ 1000.0f) * thisSize;
                contentStream.setStrokingColor(Color.red);
                contentStream.moveTo(currentX + charMinX/2, 10 + charMinY/2);
                contentStream.lineTo(currentX + charMinX/2, 10 + charMinY/2 + height/2);
                contentStream.lineTo(currentX + charMinX/2 + width/2, 10 + charMinY/2 + height/2);
                contentStream.lineTo(currentX + charMinX/2 + width/2, 10 + charMinY/2);
                contentStream.lineTo(currentX + charMinX/2, 10 + charMinY/2);
                contentStream.stroke();
                contentStream.setStrokingColor(Color.green);
                contentStream.moveTo(currentX + charX, 10 + charY);
                contentStream.lineTo(currentX + charX, 10 + charY + height);
                contentStream.lineTo(currentX + charX + width, 10 + charY + height);
                contentStream.lineTo(currentX + charX + width, 10 + charY);    
                contentStream.lineTo(currentX + charX, 10 + charY);
                contentStream.stroke();
                contentStream.setStrokingColor(Color.yellow);
                contentStream.moveTo(currentX, 10);
                contentStream.lineTo(currentX, 10 + height);
                contentStream.lineTo(currentX + width, 10 + height);
                contentStream.lineTo(currentX + width, 10);
                contentStream.lineTo(currentX, 10);
                contentStream.stroke();
                contentStream.beginText();
                contentStream.setFont(font, thisSize);
                contentStream.newLineAtOffset(currentX, 10);
                currentX = currentX + 30;
                contentStream.showText(thisCharString);
                contentStream.endText();     
            }
            contentStream.close();                  
            document.save("C:\\temp\\DrawBB.pdf");
            document.close();                
        }catch(IOException ex) {
            Logger.getLogger(DrawBoundngBox.class.getName()).log(Level.SEVERE, null, ex);
        }    
    }
}

标签: pdfbox

解决方案


推荐阅读