Example usage for org.apache.pdfbox.pdmodel.common PDRectangle getHeight

List of usage examples for org.apache.pdfbox.pdmodel.common PDRectangle getHeight

Introduction

In this page you can find the example usage for org.apache.pdfbox.pdmodel.common PDRectangle getHeight.

Prototype

public float getHeight() 

Source Link

Document

This will get the height of this rectangle as calculated by upperRightY - lowerLeftY.

Usage

From source file:jlotoprint.PrintViewUIPanelController.java

public PDDocument generatePDF() throws Exception {

    PDDocument doc = null;/*from   w w w  .jav  a2s .  co  m*/
    PDPage page = null;
    PDPageContentStream content = null;

    try {
        doc = new PDDocument();
        List<Group> pageList = importPageList(Template.getSourceFile(), Template.getModel());
        for (Parent node : pageList) {

            page = new PDPage(PDPage.PAGE_SIZE_A4);

            doc.addPage(page);

            PDRectangle mediaBox = page.getMediaBox();
            float pageWidth = mediaBox.getWidth();
            float pageHeight = mediaBox.getHeight();

            node.setTranslateX(0);
            node.setTranslateY(0);
            node.setScaleX(1);
            node.setScaleY(1);
            node.applyCss();
            node.layout();
            HashMap<String, Double> result = resizeProportional(node.getBoundsInParent().getWidth(),
                    node.getBoundsInParent().getHeight(), pageWidth, pageHeight, true);

            //get node image
            WritableImage nodeImage = node.snapshot(null, null);
            BufferedImage bufferedImage = SwingFXUtils.fromFXImage(nodeImage, null);

            //set page content
            content = new PDPageContentStream(doc, page);

            PDJpeg image = new PDJpeg(doc, bufferedImage, 1f);
            content.drawXObject(image, 0, 0, result.get("width").intValue(), result.get("height").intValue());

            content.close();
        }
    } catch (Exception ex) {
        throw ex;
    } finally {
        try {
            if (content != null) {
                content.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    return doc;
}

From source file:jp.qpg.PDFPrinter.java

License:Apache License

/**
 * @param page page size//from w  ww .j  a  v a 2 s.  c o  m
 * @param isLandscape true: landscape, false: portrait
 * @return this
 */
public PDFPrinter setPageSize(PDRectangle page, boolean isLandscape) {
    Objects.requireNonNull(page);
    pageSize = isLandscape ? new PDRectangle(page.getHeight(), page.getWidth()) : page;
    return this;
}

From source file:net.bookinaction.ExtractAnnotations.java

License:Apache License

public void doJob(String job, Float[] pA) throws IOException {

    PDDocument document = null;/*from  w w w  .j a v  a2s .  c om*/

    Stamper s = new Stamper(); // utility class

    final String job_file = job + ".pdf";
    final String dic_file = job + "-dict.txt";
    final String new_job = job + "-new.pdf";

    PrintWriter writer = new PrintWriter(dic_file);

    ImageLocationListener imageLocationsListener = new ImageLocationListener();
    AnnotationMaker annotMaker = new AnnotationMaker();

    try {
        document = PDDocument.load(new File(job_file));

        int pageNum = 0;
        for (PDPage page : document.getPages()) {
            pageNum++;

            PDRectangle cropBox = page.getCropBox();

            List<PDAnnotation> annotations = page.getAnnotations();

            // extract image locations
            List<Rectangle2D> imageRects = new ArrayList<Rectangle2D>();
            imageLocationsListener.setImageRects(imageRects);
            imageLocationsListener.processPage(page);

            int im = 0;
            for (Rectangle2D pdImageRect : imageRects) {
                s.recordImage(writer, pageNum, "[im" + im + "]", (Rectangle2D.Float) pdImageRect);
                annotations.add(annotMaker.squareAnnotation(Color.YELLOW, (Rectangle2D.Float) pdImageRect,
                        "[im" + im + "]"));
                im++;
            }

            PDFTextStripperByArea stripper = new PDFTextStripperByArea();

            int j = 0;
            List<PDAnnotation> viableAnnots = new ArrayList();

            for (PDAnnotation annot : annotations) {
                if (annot instanceof PDAnnotationTextMarkup || annot instanceof PDAnnotationLink) {

                    stripper.addRegion(Integer.toString(j++), s.getAwtRect(
                            s.adjustedRect(annot.getRectangle(), pA[0], pA[1], pA[2], pA[3]), cropBox));
                    viableAnnots.add(annot);

                } else if (annot instanceof PDAnnotationPopup || annot instanceof PDAnnotationText) {
                    viableAnnots.add(annot);

                }
            }

            stripper.extractRegions(page);

            List<PDRectangle> rects = new ArrayList<PDRectangle>();

            List<String> comments = new ArrayList<String>();
            List<String> highlightTexts = new ArrayList<String>();

            j = 0;
            for (PDAnnotation viableAnnot : viableAnnots) {

                if (viableAnnot instanceof PDAnnotationTextMarkup) {
                    String highlightText = stripper.getTextForRegion(Integer.toString(j++));
                    String withoutCR = highlightText.replace((char) 0x0A, '^');

                    String comment = viableAnnot.getContents();

                    String colorString = String.format("%06x", viableAnnot.getColor().toRGB());

                    PDRectangle aRect = s.adjustedRect(viableAnnot.getRectangle(), pA[4], pA[5], pA[6], pA[7]);
                    rects.add(aRect);
                    comments.add(comment);
                    highlightTexts.add(highlightText);

                    s.recordTextMarkup(writer, pageNum, comment, withoutCR, aRect, colorString);

                } else if (viableAnnot instanceof PDAnnotationText) {
                    String comment = viableAnnot.getContents();
                    String colorString = String.format("%06x", viableAnnot.getColor().toRGB());

                    for (Rectangle2D pdImageRect : imageRects) {
                        if (pdImageRect.contains(viableAnnot.getRectangle().getLowerLeftX(),
                                viableAnnot.getRectangle().getLowerLeftY())) {
                            s.recordTextMarkup(writer, pageNum, comment, "", (Rectangle2D.Float) pdImageRect,
                                    colorString);
                            annotations.add(annotMaker.squareAnnotation(Color.GREEN,
                                    (Rectangle2D.Float) pdImageRect, comment));
                        }
                        ;
                    }
                }
            }
            PDPageContentStream canvas = new PDPageContentStream(document, page, true, true, true);

            int i = 0;
            for (PDRectangle pdRect : rects) {
                String comment = comments.get(i);
                String highlightText = highlightTexts.get(i);
                //annotations.add(linkAnnotation(pdRect, comment, highlightText));
                //annotations.add(annotationSquareCircle(pdRect, BLUE));
                s.showBox(canvas, new Rectangle2D.Float(pdRect.getLowerLeftX(), pdRect.getUpperRightY(),
                        pdRect.getWidth(), pdRect.getHeight()), cropBox, Color.BLUE);

                i++;
            }
            canvas.close();
        }
        writer.close();
        document.save(new_job);

    } finally {
        if (document != null) {
            document.close();
        }

    }

}

From source file:no.digipost.print.validate.PdfValidator.java

License:Apache License

private boolean harUgyldigeDimensjoner(final PDPage page) {
    PDRectangle pageMediaBox = page.findMediaBox();
    long pageHeightInMillimeters = pointsTomm(pageMediaBox.getHeight());
    long pageWidthInMillimeters = pointsTomm(pageMediaBox.getWidth());
    if ((pageHeightInMillimeters != A4_HEIGHT_MM) || (pageWidthInMillimeters != A4_WIDTH_MM)) {
        LOG.info(//from  w ww . ja  v  a 2 s . c  om
                "En eller flere sider i PDF-en har ikke godkjente dimensjoner.  Godkjente dimensjoner er bredde {} mm og hyde {} mm. "
                        + "Faktiske dimensjoner er bredde {} mm og hyde: {} mm.",
                new Object[] { A4_WIDTH_MM, A4_HEIGHT_MM, pageWidthInMillimeters, pageHeightInMillimeters });
        return true;
    } else {
        return false;
    }
}

From source file:org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter.java

License:Apache License

/**
 * Creates a stream (from FOP's PDF library) from a PDF page parsed with PDFBox.
 * @param sourceDoc the source PDF the given page to be copied belongs to
 * @param page the page to transform into a stream
 * @param key value to use as key for the stream
 * @param atdoc adjustment for stream//from  ww w.  jav  a2  s .  c om
 * @param fontinfo fonts
 * @param pos rectangle
 * @return the stream
 * @throws IOException if an I/O error occurs
 */
public String createStreamFromPDFBoxPage(PDDocument sourceDoc, PDPage page, String key, AffineTransform atdoc,
        FontInfo fontinfo, Rectangle pos) throws IOException {
    handleAnnotations(sourceDoc, page, atdoc);
    if (pageNumbers.containsKey(targetPage.getPageIndex())) {
        pageNumbers.get(targetPage.getPageIndex()).set(0, targetPage.makeReference());
    }
    PDResources sourcePageResources = page.getResources();
    PDStream pdStream = getContents(page);

    COSDictionary fonts = (COSDictionary) sourcePageResources.getCOSObject().getDictionaryObject(COSName.FONT);
    COSDictionary fontsBackup = null;
    UniqueName uniqueName = new UniqueName(key, sourcePageResources);
    String newStream = null;
    if (fonts != null && pdfDoc.isMergeFontsEnabled()) {
        fontsBackup = new COSDictionary(fonts);
        MergeFontsPDFWriter m = new MergeFontsPDFWriter(fonts, fontinfo, uniqueName, parentFonts, currentMCID);
        newStream = m.writeText(pdStream);
        //            if (newStream != null) {
        //                for (Object f : fonts.keySet().toArray()) {
        //                    COSDictionary fontdata = (COSDictionary)fonts.getDictionaryObject((COSName)f);
        //                    if (getUniqueFontName(fontdata) != null) {
        //                        fonts.removeItem((COSName)f);
        //                    }
        //                }
        //            }
    }
    if (newStream == null) {
        PDFWriter writer = new PDFWriter(uniqueName, currentMCID);
        newStream = writer.writeText(pdStream);
        currentMCID = writer.getCurrentMCID();

    }
    pdStream = new PDStream(sourceDoc, new ByteArrayInputStream(newStream.getBytes("ISO-8859-1")));
    mergeXObj(sourcePageResources.getCOSObject(), fontinfo, uniqueName);
    PDFDictionary pageResources = (PDFDictionary) cloneForNewDocument(sourcePageResources.getCOSObject());

    PDFDictionary fontDict = (PDFDictionary) pageResources.get("Font");
    if (fontDict != null && pdfDoc.isMergeFontsEnabled()) {
        for (Map.Entry<String, Typeface> fontEntry : fontinfo.getUsedFonts().entrySet()) {
            Typeface font = fontEntry.getValue();
            if (font instanceof FOPPDFFont) {
                FOPPDFFont pdfFont = (FOPPDFFont) font;
                if (pdfFont.getRef() == null) {
                    pdfFont.setRef(new PDFDictionary());
                    pdfDoc.assignObjectNumber(pdfFont.getRef());
                }
                fontDict.put(fontEntry.getKey(), pdfFont.getRef());
            }
        }
    }
    updateXObj(sourcePageResources.getCOSObject(), pageResources);
    if (fontsBackup != null) {
        sourcePageResources.getCOSObject().setItem(COSName.FONT, fontsBackup);
    }

    COSStream originalPageContents = pdStream.getCOSObject();

    bindOptionalContent(sourceDoc);

    PDFStream pageStream;
    Set filter;
    //        if (originalPageContents instanceof COSStreamArray) {
    //            COSStreamArray array = (COSStreamArray)originalPageContents;
    //            pageStream = new PDFStream();
    //            InputStream in = array.getUnfilteredStream();
    //            OutputStream out = pageStream.getBufferOutputStream();
    //            IOUtils.copyLarge(in, out);
    //            filter = FILTER_FILTER;
    //        } else {
    pageStream = (PDFStream) cloneForNewDocument(originalPageContents);
    filter = Collections.EMPTY_SET;
    //        }
    if (pageStream == null) {
        pageStream = new PDFStream();
    }
    if (originalPageContents != null) {
        transferDict(originalPageContents, pageStream, filter);
    }

    transferPageDict(fonts, uniqueName, sourcePageResources);

    PDRectangle mediaBox = page.getMediaBox();
    PDRectangle cropBox = page.getCropBox();
    PDRectangle viewBox = cropBox != null ? cropBox : mediaBox;

    //Handle the /Rotation entry on the page dict
    int rotation = PDFUtil.getNormalizedRotation(page);

    //Transform to FOP's user space
    float w = (float) pos.getWidth() / 1000f;
    float h = (float) pos.getHeight() / 1000f;
    if (rotation == 90 || rotation == 270) {
        float tmp = w;
        w = h;
        h = tmp;
    }
    atdoc.setTransform(AffineTransform.getScaleInstance(w / viewBox.getWidth(), h / viewBox.getHeight()));
    atdoc.translate(0, viewBox.getHeight());
    atdoc.rotate(-Math.PI);
    atdoc.scale(-1, 1);
    atdoc.translate(-viewBox.getLowerLeftX(), -viewBox.getLowerLeftY());

    rotate(rotation, viewBox, atdoc);

    StringBuilder boxStr = new StringBuilder();
    boxStr.append(PDFNumber.doubleOut(mediaBox.getLowerLeftX())).append(' ')
            .append(PDFNumber.doubleOut(mediaBox.getLowerLeftY())).append(' ')
            .append(PDFNumber.doubleOut(mediaBox.getWidth())).append(' ')
            .append(PDFNumber.doubleOut(mediaBox.getHeight())).append(" re W n\n");
    return boxStr.toString() + IOUtils.toString(pdStream.createInputStream(null), "ISO-8859-1");
}

From source file:org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter.java

License:Apache License

private void rotate(int rotation, PDRectangle viewBox, AffineTransform atdoc) {
    float x = viewBox.getWidth() + viewBox.getLowerLeftX();
    float y = viewBox.getHeight() + viewBox.getLowerLeftY();
    switch (rotation) {
    case 90://from  w w w  .  j a va 2 s. c  om
        atdoc.scale(viewBox.getWidth() / viewBox.getHeight(), viewBox.getHeight() / viewBox.getWidth());
        atdoc.translate(0, viewBox.getWidth());
        atdoc.rotate(-Math.PI / 2.0);
        atdoc.scale(viewBox.getWidth() / viewBox.getHeight(), viewBox.getHeight() / viewBox.getWidth());
        break;
    case 180:
        atdoc.translate(x, y);
        atdoc.rotate(-Math.PI);
        atdoc.translate(-viewBox.getLowerLeftX(), -viewBox.getLowerLeftY());
        break;
    case 270:
        atdoc.translate(viewBox.getLowerLeftX(), y);
        atdoc.rotate(Math.toRadians(270 + 180));
        atdoc.translate(-x, -y);
        break;
    default:
        //no additional transformations necessary
        break;
    }
}

From source file:org.apache.fop.render.pdf.pdfbox.PreloaderPDF.java

License:Apache License

private ImageInfo loadPDF(String uri, Source src, ImageContext context) throws IOException, ImageException {
    int selectedPage = ImageUtil.needPageIndexFromURI(uri);

    URI docURI = deriveDocumentURI(src.getSystemId());

    PDDocument pddoc = getDocument(context, docURI, src);
    pddoc = Interceptors.getInstance().interceptOnLoad(pddoc, docURI);

    //Disable the warning about a missing close since we rely on the GC to decide when
    //the cached PDF shall be disposed off.
    pddoc.getDocument().setWarnMissingClose(false);

    int pageCount = pddoc.getNumberOfPages();
    if (selectedPage < 0 || selectedPage >= pageCount) {
        throw new ImageException("Selected page (index: " + selectedPage
                + ") does not exist in the PDF file. The document has " + pddoc.getNumberOfPages() + " pages.");
    }//w w w .  j a  va 2s  . c  o  m
    PDPage page = pddoc.getDocumentCatalog().getPages().get(selectedPage);
    PDRectangle mediaBox = page.getMediaBox();
    PDRectangle cropBox = page.getCropBox();
    PDRectangle viewBox = cropBox != null ? cropBox : mediaBox;
    int w = Math.round(viewBox.getWidth() * 1000);
    int h = Math.round(viewBox.getHeight() * 1000);

    //Handle the /Rotation entry on the page dict
    int rotation = PDFUtil.getNormalizedRotation(page);
    if (rotation == 90 || rotation == 270) {
        //Swap width and height
        int exch = w;
        w = h;
        h = exch;
    }

    ImageSize size = new ImageSize();
    size.setSizeInMillipoints(w, h);
    size.setResolution(context.getSourceResolution());
    size.calcPixelsFromSize();

    ImageInfo info = new ImageInfo(uri, ImagePDF.MIME_PDF);
    info.setSize(size);
    info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, new ImagePDF(info, pddoc));

    int lastPageIndex = pddoc.getNumberOfPages() - 1;
    if (selectedPage < lastPageIndex) {
        info.getCustomObjects().put(ImageInfo.HAS_MORE_IMAGES, Boolean.TRUE);
    }

    return info;
}

From source file:org.elacin.pdfextract.datasource.pdfbox.PDFBoxIntegration.java

License:Apache License

private void correctPosition(@NotNull final PDFont fontObj, final byte[] string, final int i,
        @NotNull final String c, final float fontSizeText, final float glyphSpaceToTextSpaceFactor,
        float horizontalScalingText, final int codeLength, @NotNull final ETextPosition text)
        throws IOException {

    /**//  w w w  . j av  a2s.c om
     * Provide precise positioning of glyphs.
     *
     * There are several problems right which needs to be worked around:
     *
     * 1. Sometimes the PDF will make room for a glyph which belongs to a font with
     *      one or more very tall glyphs by jumping up on the page before drawing.
     *   Since most glyphs are (much) shorter than the tallest one, we need to make
     *      up for that by adjusting the Y coordinate back down. The distance which
     *      is jumped up is embedded in the PDF files, so there is no other way to go
     *      about this.
     *
     *  'beforeRoomForGlyph' is the position we were at before the jump back.
     *   Then we need to add spaceOverChar which is my estimate of where the glyph
     *      should begin. the result is kept in 'startY'
     *
     * 2. The default height we get might also be too big, so recalculate that based
     *      on character bounding
     *
     */
    final BoundingBox character = fontObj.getCharacterBoundingBox(string, i, codeLength);
    PDRectangle fontBB = null;

    try {
        fontBB = fontObj.getFontBoundingBox();
    } catch (RuntimeException e) {

        // ignore, this is frequently not implemented
    }

    final Rectangle pos = text.getPos();
    float adjust = (fontSizeText * horizontalScalingText) / glyphSpaceToTextSpaceFactor;

    adjust *= getTextMatrix().getXScale();

    final Rectangle newPos;

    if ((character != null) && (fontBB != null) && (character.getHeight() > 0.0f)
            && (fontBB.getHeight() > 0.0f)) {

        /* remove the upper and lower bounds filtered away by character */
        final float spaceUnderChar = Math.min(fontBB.getLowerLeftY(), character.getLowerLeftY());
        final float spaceOverChar = fontBB.getUpperRightY() - character.getUpperRightY();
        final float fontHeight = fontBB.getHeight();

        /* calculate the upper left corner of the rendered glyph */
        float yStart = pos.endY - adjust * fontHeight;
        yStart += adjust * spaceOverChar;
        yStart -= adjust * spaceUnderChar;
        yStart -= pos.height;

        /* determine start X coordinate. */
        final float x;

        if (isMonoSpacedFont(fontObj)) {
            x = pos.x;
        } else {
            //                float leftOfText = text.getX() - (adjust * fontBB.getWidth());
            //
            //                x = leftOfText + adjust * character.getLowerLeftX();
            x = pos.x;
        }

        /*
         *  It was much easier to write the word segmentation code with full font width,
         *   so lets keep that. I havent seen this causing any problems
         */
        float w = pos.width;

        /*
         *  Line segmentation code was obviously much easier by not having any descenders which
         *   can even overlap into the following line. Math symbols need to stay full length
         */
        final float characterHeight;

        if (NO_DESCENDERS && (Character.getType(c.charAt(0)) != (int) Character.MATH_SYMBOL)) {
            characterHeight = character.getUpperRightY();
        } else {
            characterHeight = character.getHeight();
        }

        float h = adjust * (characterHeight);

        /* correct if the NO_DESCENDERS hack made this character have no height*/
        if (NO_DESCENDERS && h < 0.1f) {
            h = pos.height;
        }

        newPos = new Rectangle(x, yStart, w, h);
    } else {

        /*
         *  here we have a lot less information, so keep most of what was calculated. Just offset
         *   the Y coordinate
         */
        float h = pos.height;
        float w = pos.width;
        float startY = pos.y - h;// * 0.8f;

        if (fontObj instanceof PDType3Font) {

            /*
             *  type 3 fonts typically have almost no information
             * try to mitigate the damage by keeping them small.
             */
            h *= 0.5f;
            startY += h; /* this is a _very_ quick and dirty hack */
        }

        newPos = new Rectangle(pos.x, startY, w, h);
    }

    if (log.isTraceEnabled()) {
        log.trace("LOG00730:Text " + c + ", " + "pos from " + pos + " to " + newPos);
    }

    text.setBaseLine(pos.y);
    text.setPos(newPos);
}

From source file:org.elacin.pdfextract.datasource.pdfbox.PDFBoxIntegration.java

License:Apache License

/**
 * This will process the contents of a page.
 *
 * @param page    The page to process./*from   w  ww  . ja  v  a2 s . co  m*/
 * @param content The contents of the page.
 * @throws IOException If there is an error processing the page.
 */
protected void processPage(@NotNull PDPage page, COSStream content) throws IOException {

    if ((currentPageNo >= startPage) && (currentPageNo <= endPage)) {

        /* show which page we are working on in the log */
        MDC.put("page", currentPageNo);
        charactersForPage.clear();
        characterListMapping.clear();
        pageSize = page.findCropBox().createDimension();
        rotation = (float) page.findRotation();

        /* this is used to 'draw' images on during pdf parsing */
        graphicsDrawer.clearSurface();
        setGraphicsState(null);
        resetEngine();
        processStream(page, page.findResources(), content);
        filterOutBadFonts(charactersForPage);

        /* filter out remaining definite bad characters */
        filterOutControlCodes(charactersForPage);

        List<PhysicalText> texts = new ArrayList<PhysicalText>(charactersForPage.size());

        for (ETextPosition tp : charactersForPage) {
            texts.add(tp.convertText(fonts));
        }

        final PDRectangle mediaBox = page.findMediaBox();
        Rectangle dimensions = new Rectangle(mediaBox.getLowerLeftX(), mediaBox.getLowerLeftY(),
                mediaBox.getWidth(), mediaBox.getHeight());
        PageContent thisPage = new PageContent(texts, graphicsDrawer.getGraphicContents(), currentPageNo,
                dimensions);

        docContent.addPage(thisPage);
        MDC.remove("page");
    }
}

From source file:org.esteco.jira.pdf.UsingTextMatrix.java

License:Apache License

/**
 * creates a sample document with some text using a text matrix.
 *
 * @param message The message to write in the file.
 * @param outfile The resulting PDF./*from   ww w. jav a  2 s . c  o m*/
 * @throws IOException If there is an error writing the data.
 */
public void doIt(String message, String outfile) throws IOException {
    // the document
    PDDocument doc = null;
    try {
        doc = new PDDocument();

        // Page 1
        PDFont font = PDType1Font.HELVETICA;
        PDPage page = new PDPage(PDRectangle.A4);
        doc.addPage(page);
        float fontSize = 12.0f;

        PDRectangle pageSize = page.getMediaBox();
        float centeredXPosition = (pageSize.getWidth() - fontSize / 1000f) / 2f;
        float stringWidth = font.getStringWidth(message);
        float centeredYPosition = (pageSize.getHeight() - (stringWidth * fontSize) / 1000f) / 3f;

        PDPageContentStream contentStream = new PDPageContentStream(doc, page, AppendMode.OVERWRITE, false);
        contentStream.setFont(font, fontSize);
        contentStream.beginText();
        // counterclockwise rotation
        for (int i = 0; i < 8; i++) {
            contentStream.setTextMatrix(Matrix.getRotateInstance(i * Math.PI * 0.25, centeredXPosition,
                    pageSize.getHeight() - centeredYPosition));
            contentStream.showText(message + " " + i);
        }
        // clockwise rotation
        for (int i = 0; i < 8; i++) {
            contentStream.setTextMatrix(
                    Matrix.getRotateInstance(-i * Math.PI * 0.25, centeredXPosition, centeredYPosition));
            contentStream.showText(message + " " + i);
        }

        contentStream.endText();
        contentStream.close();

        // Page 2
        page = new PDPage(PDRectangle.A4);
        doc.addPage(page);
        fontSize = 1.0f;

        contentStream = new PDPageContentStream(doc, page, AppendMode.OVERWRITE, false);
        contentStream.setFont(font, fontSize);
        contentStream.beginText();

        // text scaling and translation
        for (int i = 0; i < 10; i++) {
            contentStream.setTextMatrix(new Matrix(12 + (i * 6), 0, 0, 12 + (i * 6), 100, 100 + i * 50));
            contentStream.showText(message + " " + i);
        }
        contentStream.endText();
        contentStream.close();

        // Page 3
        page = new PDPage(PDRectangle.A4);
        doc.addPage(page);
        fontSize = 1.0f;

        contentStream = new PDPageContentStream(doc, page, AppendMode.OVERWRITE, false);
        contentStream.setFont(font, fontSize);
        contentStream.beginText();

        int i = 0;
        // text scaling combined with rotation
        contentStream.setTextMatrix(new Matrix(12, 0, 0, 12, centeredXPosition, centeredYPosition * 1.5f));
        contentStream.showText(message + " " + i++);

        contentStream.setTextMatrix(new Matrix(0, 18, -18, 0, centeredXPosition, centeredYPosition * 1.5f));
        contentStream.showText(message + " " + i++);

        contentStream.setTextMatrix(new Matrix(-24, 0, 0, -24, centeredXPosition, centeredYPosition * 1.5f));
        contentStream.showText(message + " " + i++);

        contentStream.setTextMatrix(new Matrix(0, -30, 30, 0, centeredXPosition, centeredYPosition * 1.5f));
        contentStream.showText(message + " " + i++);

        contentStream.endText();
        contentStream.close();

        doc.save(outfile);
    } finally {
        if (doc != null) {
            doc.close();
        }
    }
}