ralfstuckert / pdfbox-layout

MIT License
156 stars 74 forks source link

Get Position Of Text #16

Closed atown45 closed 7 years ago

atown45 commented 7 years ago

Hello,

Is it possible to get the position of text after it has been added to a paragraph? Using the following, I'd like to be able to find the position (x,y) of where NAME has been added the paragraph.

Paragraph paragraph = new Paragraph(); paragraph.addText("NAME", 12, BaseFont.Times.getPlainFont()); document.add(paragraph, VerticalLayoutHint.RIGHT);

Thanks you.

ralfstuckert commented 7 years ago

Sorry, layouting is done dynamically during the rendering process. What exactly is your usecase, maybe there is another solution...

atown45 commented 7 years ago

I was hoping to be able to get the position in order to use raw PDFBox (moveto(), lineto(), strike()) to draw an underline under the text.

ralfstuckert commented 7 years ago

I'm currently refactoring some parts, so hopefully the next days will be a release that at least provides a wordaround for you.

atown45 commented 7 years ago

That's fantastic!! Thank you very much!

ralfstuckert commented 7 years ago

Refactoring is done in version 0.8.5, you can now do your own annotations. In the following example I implemented an UnderlineAnnotation that draws adds an annotation of type underline to the document. You could have done this simpler by directly drawing a line, but I prefered the PDF-way here.

I will try to refactor the markup section the next days, so you can also do custom markup for annotations, this will (hopefully) ease up things for the user.

Regards Ralf

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup;

import rst.pdfbox.layout.elements.Document;
import rst.pdfbox.layout.elements.PageFormat;
import rst.pdfbox.layout.elements.Paragraph;
import rst.pdfbox.layout.text.DrawContext;
import rst.pdfbox.layout.text.Position;
import rst.pdfbox.layout.text.StyledText;
import rst.pdfbox.layout.text.annotations.Annotated;
import rst.pdfbox.layout.text.annotations.AnnotatedStyledText;
import rst.pdfbox.layout.text.annotations.Annotation;
import rst.pdfbox.layout.text.annotations.AnnotationProcessor;
import rst.pdfbox.layout.text.annotations.AnnotationProcessorFactory;
import rst.pdfbox.layout.util.CompatibilityHelper;

public class CustomAnnotation {

    public static void main(String[] args) throws Exception {

    AnnotationProcessorFactory.register(UnderlineAnnotationProcessor.class);

    Document document = new Document(PageFormat.with().A4().portrait().build());

    Paragraph paragraph = new Paragraph();
    paragraph.addText("Hello there, here is ", 10, PDType1Font.COURIER);

    AnnotatedStyledText underlinedText = new AnnotatedStyledText(
        "underlined text", 10, PDType1Font.COURIER, Color.black, null);
    underlinedText.addAnnotation(new UnderlineAnnotation());
    paragraph.add(underlinedText);

    paragraph.addText(". Do whatever you want here...underline, strike, highlight, whatsoever", 10,
        PDType1Font.COURIER);

    paragraph.setMaxWidth(200);
    document.add(paragraph);

    final OutputStream outputStream = new FileOutputStream(
        "customannotation.pdf");
    document.save(outputStream);
    }

    public static class UnderlineAnnotation implements Annotation {

    private Color color;

    public UnderlineAnnotation() {
        this(null);
    }

    public UnderlineAnnotation(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }
    }

    public static class UnderlineAnnotationProcessor implements
        AnnotationProcessor {

    @Override
    public void annotatedObjectDrawn(Annotated drawnObject,
        DrawContext drawContext, Position upperLeft, float width,
        float height) throws IOException {

        Iterable<UnderlineAnnotation> underlineAnnotations = drawnObject
            .getAnnotationsOfType(UnderlineAnnotation.class);

        for (UnderlineAnnotation underlineAnnotation : underlineAnnotations) {

        PDAnnotationTextMarkup markup = new PDAnnotationTextMarkup(
            PDAnnotationTextMarkup.SUB_TYPE_UNDERLINE);

        PDRectangle bounds = new PDRectangle();
        bounds.setLowerLeftX(upperLeft.getX());
        bounds.setLowerLeftY(upperLeft.getY() - height);
        bounds.setUpperRightX(upperLeft.getX() + width);
        bounds.setUpperRightY(upperLeft.getY());
        markup.setRectangle(bounds);
        float[] quadPoints = CompatibilityHelper.toQuadPoints(bounds);
        markup.setQuadPoints(quadPoints);

        Color color = underlineAnnotation.getColor();
        if (color == null) {
            if (drawnObject instanceof StyledText) {
            color = ((StyledText) drawnObject).getColor();
            }
        }
        if (color != null) {
            CompatibilityHelper.setAnnotationColor(markup, color);
        }

        drawContext.getCurrentPage().getAnnotations().add(markup);
        }
    }

    @Override
    public void beforePage(DrawContext drawContext) throws IOException {
        // nothing to do here for us
    }

    @Override
    public void afterPage(DrawContext drawContext) throws IOException {
        // nothing to do here for us
    }

    @Override
    public void afterRender(PDDocument document) throws IOException {
        // nothing to do here for us
    }

    }

}
ralfstuckert commented 7 years ago

With 0.9.0 you can do even markup for custom annotations, see the wiki