Ограничительная рамка TextPosition PDFBox - PullRequest
0 голосов
/ 04 января 2019

Я пытаюсь из TextPosition нарисовать соответствующую ограничивающую рамку глифа, как показано в документации PDF 32000. enter image description here

Вот моя функция, которая выполняет вычисления от пространства глифов до пространства пользователя

@Override 
protected void processTextPosition(TextPosition text) {
    PDFont font = pos.getFont();

    BoundingBox bbox = font.getBoundingBox();

    Rectangle2D.Float rect = new Rectangle2D.Float(bbox.getLowerLeftX(), bbox.getUpperRightY(), 
            bbox.getWidth(), bbox.getHeight());

    AffineTransform at = pos.getTextMatrix().createAffineTransform();

    if (font instanceof PDType3Font) {
        at.concatenate(font.getFontMatrix().createAffineTransform());
    } else {
        at.scale(1 / 1000f, 1 / 1000f);
    }
    Shape shape = at.createTransformedShape(rect);
    rectangles.add(fillBBox(text));


    super.processTextPosition(text);
}

А вот функция, которая рисует извлеченные прямоугольники:

private void drawBoundingBoxes() throws IOException {

    String fileNameOut = path.substring(0, path.lastIndexOf(".")) + "_OUT.pdf";
    log.info("Drawing Bounding Boxes for TextPositions");

    PDPageContentStream contentStream = new PDPageContentStream(document, 
            document.getPage(document.getNumberOfPages()-1),
            PDPageContentStream.AppendMode.APPEND, false , true );
    contentStream.setLineWidth(1f);
    contentStream.setStrokingColor(Color.RED);

    try{
        for (Shape p : rectangles) {
            p = all.get(0);
        double[] coords = new double[6];
        GeneralPath g = new GeneralPath(p.getBounds2D());
        for (PathIterator pi = g.getPathIterator(null);
             !pi.isDone();
             pi.next()) {
            System.out.println(Arrays.toString(coords));
            switch (pi.currentSegment(coords)) {
            case PathIterator.SEG_MOVETO:
                System.out.println("move to");
                contentStream.moveTo ((float)coords[0], (float) coords[1]);
                break;

            case PathIterator.SEG_LINETO:
                System.out.println("line to");
                contentStream.lineTo ((float)coords[0], (float) coords[1]);
                break;

            case PathIterator.SEG_CUBICTO:
                System.out.println("cubc to");
                contentStream.curveTo((float)coords[0], (float) coords[1],
                        (float)coords[2], (float) coords[3], 
                        (float)coords[4],(float) coords[5]);
                break;

            case PathIterator.SEG_CLOSE:
                System.out.println("close");
                contentStream.closeAndStroke();
                break;
            default:
                System.out.println("no shatt");
                break;
            }

        }

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        contentStream.close();
        document.save(new File(fileNameOut));
    }
}

Затем, когда я пытаюсь нарисовать на PDF, я получаю следующий результат для первой буквы (заглавная V) enter image description here

Я не могу понять, что я делаю неправильно. Есть идеи?

1 Ответ

0 голосов
/ 04 января 2019

г. D

Я проверил ваш код, и единственное изменение, которое мне было нужно для его работы, - это инвертировать ось Y Причина, по которой это необходимо, заключается в том, что источник в PDF User Space расположен в нижнем левом углу, в отличие от источника Java 2D User Space , который расположен в верхней части. левый угол [1] .

8.3.2.3 Пространство пользователя

Система координат пространства пользователя должна быть инициализирована в состояние по умолчанию для каждой страницы документа. Запись CropBox в словаре страницы должна указывать прямоугольник пользовательского пространства, соответствующий видимой области предполагаемого выходного носителя (окно отображения или печатная страница). Положительная ось x проходит горизонтально вправо, а положительная ось y вертикально вверх, как в стандартной математической практике (может быть изменено с помощью записи Rotate в словаре страницы). Длина единицы по осям x и y задается записью UserUnit (PDF 1.6) в словаре страницы (см. Таблицу 30). Если эта запись отсутствует или поддерживается, используется значение по умолчанию 1⁄72 дюйма. Эта система координат называется пользовательским пространством по умолчанию. [2]

Исходный код

@Override 
protected void processTextPosition(TextPosition text) {
    try {
        PDFont font = pos.getFont();

        BoundingBox bbox = font.getBoundingBox();

        Rectangle2D.Float rect = new Rectangle2D.Float(bbox.getLowerLeftX(), bbox.getUpperRightY(),
                    bbox.getWidth(), bbox.getHeight());

        AffineTransform at = pos.getTextMatrix().createAffineTransform();

        if (font instanceof PDType3Font) {
            at.concatenate(font.getFontMatrix().createAffineTransform());
        } else {
            at.scale(1 / 1000f, 1 / 1000f);
        }

        Shape shape = at.createTransformedShape(rect);

        // Invert Y axis
        Rectangle2D bounds = shape.getBounds2D();
        bounds.setRect(bounds.getX(), bounds.getY() - bounds.getHeight(), bounds.getWidth(), bounds.getHeight());

        rectangles.add(bounds);

        super.processTextPosition(text);

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Ссылки

  1. Концепции Java 2D API: координаты

  2. Управление документами. Переносимый формат документов. Часть 1. PDF 1.7, PDF 32000-1: 2008 , раздел 8.3: Системы координат, стр. 115

...