Нарисуйте ограничивающую рамку вокруг символа в pdfbox

Я хочу рассчитать ограничивающую рамку для каждого символа, который я рисую в PDF, для множества разных шрифтов и размеров. Кажется, что для разных шрифтов это работает по-разному, например, arial mt и elephant regular.

Например, я использовал знак -, чтобы почувствовать это, в Arial нижний левый угол - 65 440, у слона - 7 165, но слон тянется выше, и я не могу найти, откуда это движение.

Большинство шрифтов больше похожи на Arial, где верхняя часть шрифта имеет высоту / 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);
        }    
    }
}

Вы пробовали пример DrawPrintTextLocations.java из исходного кода, загруженного в подпроекте примеров?

Tilman Hausherr 26.10.2018 08:43

Ура, это почти достигает того, что мне нужно, но без раскрытия того, как это достигается, поскольку он в основном захватывает визуализированный текст и использует его ограничивающую рамку. Если это почти точно, за исключением нескольких случаев, когда поле не совсем охватывает текст, поскольку полный путь кривых не совсем включен в ограничивающий прямоугольник.

Benjamin James 27.10.2018 23:19

Он получает ограничивающую рамку путей. За исключением шрифтов type3, где они недоступны. Голубые поля должны быть точными, за исключением шрифтов type3. Есть комментарии, что означают цвета. На ваш исходный вопрос дан ответ в calculateGlyphBounds(), и он довольно сложен, потому что каждый тип шрифта рассчитывается по-разному. Re the full path of curves are not quite included in the bounding box поделитесь пожалуйста PDF. Единственная известная мне ошибка - это повернутые страницы с кадрированием.

Tilman Hausherr 28.10.2018 06:20

Ограничивающая рамка работает очень хорошо, и, как описал Тилман, голубые рамки отлично справляются со своей задачей в большинстве случаев. Как прикрепить файл, чтобы показать, где ограничивающие рамки не справляются со своей задачей?

Benjamin James 28.10.2018 23:57

загрузите в хостинг-провайдера и опубликуйте ссылку. Так, например, dropbox, google drive или filedropper.com. Не используйте хостера, который требует регистрации.

Tilman Hausherr 29.10.2018 06:35
0
5
511
0

Другие вопросы по теме