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

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

Introduction

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

Prototype

public float getUpperRightY() 

Source Link

Document

This will get the upper right y coordinate.

Usage

From source file:com.formkiq.core.service.generator.pdfbox.PDRectangleComparator.java

License:Apache License

@Override
public int compare(final PDRectangle r1, final PDRectangle r2) {

    int v1 = (int) r1.getUpperRightY();
    int v2 = (int) r2.getUpperRightY();
    int r = Integer.compare(v2, v1);

    if (r == 0) {
        v1 = (int) r1.getUpperRightX();
        v2 = (int) r2.getUpperRightX();
        r = Integer.compare(v1, v2);
    }//  ww  w.  java  2 s .co  m

    return r;
}

From source file:com.formkiq.core.service.generator.pdfbox.PDRectangleUtil.java

License:Apache License

/**
 * Calculate the Distance between two {@link PDRectangle}.
 * @param r1 {@link PDRectangle}/* w  ww. ja  v  a 2s  .c  o  m*/
 * @param r2 {@link PDRectangle}
 * @return float
 */
public static float getDistanceBetween(final PDRectangle r1, final PDRectangle r2) {
    float dx = min(
            min(abs(r1.getLowerLeftX() - r2.getLowerLeftX()), abs(r1.getUpperRightX() - r2.getUpperRightX())),
            min(abs(r1.getLowerLeftX() - r2.getUpperRightX()), abs(r1.getUpperRightX() - r2.getLowerLeftX())));

    float dy = min(
            min(abs(r1.getLowerLeftY() - r2.getLowerLeftY()), abs(r1.getUpperRightY() - r2.getUpperRightY())),
            min(abs(r1.getLowerLeftY() - r2.getUpperRightY()), abs(r1.getUpperRightY() - r2.getLowerLeftY())));

    return dx + dy;
}

From source file:com.formkiq.core.service.generator.pdfbox.TextSearchAreaFilterInsideLines.java

License:Apache License

@Override
public List<PDFieldSearchRectangle> getTextSearchArea(final PDPage page, final PDField pdField,
        final PDAnnotationWidget widget, final List<PDRectangle> lineRects) {

    List<PDFieldSearchRectangle> area = new ArrayList<>(1);
    PDRectangle wrect = widget.getRectangle();

    List<PDRectangle> leftlist = new ArrayList<>();
    List<PDRectangle> rightlist = new ArrayList<>();
    List<PDRectangle> toplist = new ArrayList<>();
    List<PDRectangle> bottomlist = new ArrayList<>();

    for (PDRectangle line : lineRects) {

        if (line.getLowerLeftY() < wrect.getLowerLeftY() && wrect.getUpperRightY() < line.getUpperRightY()) {

            if (line.getUpperRightX() < wrect.getLowerLeftX()) {
                leftlist.add(line);/*  w w  w .  ja  va  2 s  .c  o  m*/
            } else if (wrect.getUpperRightX() < line.getLowerLeftX()) {
                rightlist.add(line);
            }
        }

        if (line.getLowerLeftX() < wrect.getLowerLeftX() && wrect.getUpperRightX() < line.getUpperRightX()) {

            if (line.getUpperRightY() < wrect.getLowerLeftY()) {
                bottomlist.add(line);
            } else if (wrect.getUpperRightY() < line.getUpperRightY()) {
                toplist.add(line);
            }
        }
    }

    PDRectangle left = !leftlist.isEmpty() ? Collections.max(leftlist, new PDRectangleXComparator()) : null;
    PDRectangle right = !rightlist.isEmpty() ? Collections.min(rightlist, new PDRectangleXComparator()) : null;
    PDRectangle top = !toplist.isEmpty() ? Collections.min(toplist, new PDRectangleYComparator()) : null;
    PDRectangle bottom = !bottomlist.isEmpty() ? Collections.max(bottomlist, new PDRectangleYComparator())
            : null;

    if (left != null && right != null && top != null && bottom != null) {
        PDRectangle r = new PDRectangle(left.getLowerLeftX(), bottom.getLowerLeftY(),
                right.getUpperRightX() - left.getLowerLeftX(), top.getUpperRightY() - bottom.getLowerLeftY());

        area.add(new PDFieldSearchRectangle(PDFieldAreaSearch.RECTANGLE, r));
    }

    return area;
}

From source file:com.infoimage.infotrac.pdfbox.PDFTextAnnotator.java

License:Apache License

private float[] computeQuads(PDRectangle rect) {
    float[] quads = new float[8];
    // top left/*from   w  w w. j av  a 2  s.  co  m*/
    quads[0] = rect.getLowerLeftX(); // x1
    quads[1] = rect.getUpperRightY() - 2; // y1
    // bottom left
    quads[2] = rect.getUpperRightX(); // x2
    quads[3] = quads[1]; // y2
    // top right
    quads[4] = quads[0]; // x3
    quads[5] = rect.getLowerLeftY() - 2; // y3
    // bottom right
    quads[6] = quads[2]; // x4
    quads[7] = quads[5]; // y4
    return quads;
}

From source file:com.repeatability.pdf.PDFTextStripper.java

License:Apache License

private void fillBeadRectangles(PDPage page) {
    beadRectangles = new ArrayList<PDRectangle>();
    for (PDThreadBead bead : page.getThreadBeads()) {
        if (bead == null) {
            // can't skip, because of null entry handling in processTextPosition()
            beadRectangles.add(null);/*w  w  w .  j ava  2s. c om*/
            continue;
        }

        PDRectangle rect = bead.getRectangle();

        // bead rectangle is in PDF coordinates (y=0 is bottom),
        // glyphs are in image coordinates (y=0 is top),
        // so we must flip
        PDRectangle mediaBox = page.getMediaBox();
        float upperRightY = mediaBox.getUpperRightY() - rect.getLowerLeftY();
        float lowerLeftY = mediaBox.getUpperRightY() - rect.getUpperRightY();
        rect.setLowerLeftY(lowerLeftY);
        rect.setUpperRightY(upperRightY);

        // adjust for cropbox
        PDRectangle cropBox = page.getCropBox();
        if (cropBox.getLowerLeftX() != 0 || cropBox.getLowerLeftY() != 0) {
            rect.setLowerLeftX(rect.getLowerLeftX() - cropBox.getLowerLeftX());
            rect.setLowerLeftY(rect.getLowerLeftY() - cropBox.getLowerLeftY());
            rect.setUpperRightX(rect.getUpperRightX() - cropBox.getLowerLeftX());
            rect.setUpperRightY(rect.getUpperRightY() - cropBox.getLowerLeftY());
        }

        beadRectangles.add(rect);
    }
}

From source file:com.repeatability.pdf.PDFTextStripper.java

License:Apache License

/**
 * This will process a TextPosition object and add the text to the list of characters on a page. It takes care of
 * overlapping text./*from  w ww. j a va 2 s. c om*/
 *
 * @param text The text to process.
 */
@Override
protected void processTextPosition(TextPosition text) {
    boolean showCharacter = true;
    if (suppressDuplicateOverlappingText) {
        showCharacter = false;
        String textCharacter = text.getUnicode();
        float textX = text.getX();
        float textY = text.getY();
        TreeMap<Float, TreeSet<Float>> sameTextCharacters = characterListMapping.get(textCharacter);
        if (sameTextCharacters == null) {
            sameTextCharacters = new TreeMap<Float, TreeSet<Float>>();
            characterListMapping.put(textCharacter, sameTextCharacters);
        }
        // RDD - Here we compute the value that represents the end of the rendered
        // text. This value is used to determine whether subsequent text rendered
        // on the same line overwrites the current text.
        //
        // We subtract any positive padding to handle cases where extreme amounts
        // of padding are applied, then backed off (not sure why this is done, but there
        // are cases where the padding is on the order of 10x the character width, and
        // the TJ just backs up to compensate after each character). Also, we subtract
        // an amount to allow for kerning (a percentage of the width of the last
        // character).
        boolean suppressCharacter = false;
        float tolerance = text.getWidth() / textCharacter.length() / 3.0f;

        SortedMap<Float, TreeSet<Float>> xMatches = sameTextCharacters.subMap(textX - tolerance,
                textX + tolerance);
        for (TreeSet<Float> xMatch : xMatches.values()) {
            SortedSet<Float> yMatches = xMatch.subSet(textY - tolerance, textY + tolerance);
            if (!yMatches.isEmpty()) {
                suppressCharacter = true;
                break;
            }
        }
        if (!suppressCharacter) {
            TreeSet<Float> ySet = sameTextCharacters.get(textX);
            if (ySet == null) {
                ySet = new TreeSet<Float>();
                sameTextCharacters.put(textX, ySet);
            }
            ySet.add(textY);
            showCharacter = true;
        }
    }
    if (showCharacter) {
        // if we are showing the character then we need to determine which article it belongs to
        int foundArticleDivisionIndex = -1;
        int notFoundButFirstLeftAndAboveArticleDivisionIndex = -1;
        int notFoundButFirstLeftArticleDivisionIndex = -1;
        int notFoundButFirstAboveArticleDivisionIndex = -1;
        float x = text.getX();
        float y = text.getY();
        if (shouldSeparateByBeads) {
            for (int i = 0; i < beadRectangles.size() && foundArticleDivisionIndex == -1; i++) {
                PDRectangle rect = beadRectangles.get(i);
                if (rect != null) {
                    if (rect.contains(x, y)) {
                        foundArticleDivisionIndex = i * 2 + 1;
                    } else if ((x < rect.getLowerLeftX() || y < rect.getUpperRightY())
                            && notFoundButFirstLeftAndAboveArticleDivisionIndex == -1) {
                        notFoundButFirstLeftAndAboveArticleDivisionIndex = i * 2;
                    } else if (x < rect.getLowerLeftX() && notFoundButFirstLeftArticleDivisionIndex == -1) {
                        notFoundButFirstLeftArticleDivisionIndex = i * 2;
                    } else if (y < rect.getUpperRightY() && notFoundButFirstAboveArticleDivisionIndex == -1) {
                        notFoundButFirstAboveArticleDivisionIndex = i * 2;
                    }
                } else {
                    foundArticleDivisionIndex = 0;
                }
            }
        } else {
            foundArticleDivisionIndex = 0;
        }
        int articleDivisionIndex;
        if (foundArticleDivisionIndex != -1) {
            articleDivisionIndex = foundArticleDivisionIndex;
        } else if (notFoundButFirstLeftAndAboveArticleDivisionIndex != -1) {
            articleDivisionIndex = notFoundButFirstLeftAndAboveArticleDivisionIndex;
        } else if (notFoundButFirstLeftArticleDivisionIndex != -1) {
            articleDivisionIndex = notFoundButFirstLeftArticleDivisionIndex;
        } else if (notFoundButFirstAboveArticleDivisionIndex != -1) {
            articleDivisionIndex = notFoundButFirstAboveArticleDivisionIndex;
        } else {
            articleDivisionIndex = charactersByArticle.size() - 1;
        }

        List<TextPosition> textList = charactersByArticle.get(articleDivisionIndex);

        // In the wild, some PDF encoded documents put diacritics (accents on
        // top of characters) into a separate Tj element. When displaying them
        // graphically, the two chunks get overlayed. With text output though,
        // we need to do the overlay. This code recombines the diacritic with
        // its associated character if the two are consecutive.
        if (textList.isEmpty()) {
            textList.add(text);
        } else {
            // test if we overlap the previous entry.
            // Note that we are making an assumption that we need to only look back
            // one TextPosition to find what we are overlapping.
            // This may not always be true. */
            TextPosition previousTextPosition = textList.get(textList.size() - 1);
            if (text.isDiacritic() && previousTextPosition.contains(text)) {
                previousTextPosition.mergeDiacritic(text);
            }
            // If the previous TextPosition was the diacritic, merge it into this
            // one and remove it from the list.
            else if (previousTextPosition.isDiacritic() && text.contains(previousTextPosition)) {
                text.mergeDiacritic(previousTextPosition);
                textList.remove(textList.size() - 1);
                textList.add(text);
            } else {
                textList.add(text);
            }
        }
    }
}

From source file:com.synopsys.integration.blackduck.report.pdf.RiskReportPdfWriter.java

License:Apache License

private PDRectangle writeComponentRow(final float pageWidth, final float y, final BomComponent component,
        final boolean isOdd) throws IOException, URISyntaxException {
    final float componentNameWidth = 125F;
    final float componentVersionWidth = 115F;
    final float componentLicenseWidth = 150F;

    List<String> componentNameTextLines = new ArrayList<>();
    List<String> componentVersionTextLines = new ArrayList<>();
    List<String> componentLicenseTextLines = new ArrayList<>();

    if (StringUtils.isNotBlank(component.getComponentName())) {
        componentNameTextLines = StringManager.wrapToCombinedList(component.getComponentName(),
                Math.round(componentNameWidth));
    }/* w  w  w  .j  a  va 2s .  c  o m*/
    if (StringUtils.isNotBlank(component.getComponentVersion())) {
        componentVersionTextLines = StringManager.wrapToCombinedList(component.getComponentVersion(),
                Math.round(componentNameWidth));
    }
    if (StringUtils.isNotBlank(component.getLicense())) {
        componentLicenseTextLines = StringManager.wrapToCombinedList(component.getLicense(),
                Math.round(componentNameWidth));
    }

    float rowHeight = pdfManager.getApproximateWrappedStringHeight(componentNameTextLines.size(),
            PDFBoxManager.DEFAULT_FONT_SIZE);
    final float componentVersionHeight = pdfManager.getApproximateWrappedStringHeight(
            componentVersionTextLines.size(), PDFBoxManager.DEFAULT_FONT_SIZE);
    final float componentLicenseHeight = pdfManager.getApproximateWrappedStringHeight(
            componentLicenseTextLines.size(), PDFBoxManager.DEFAULT_FONT_SIZE);
    if (componentVersionHeight > rowHeight) {
        rowHeight = componentVersionHeight;
    }
    if (componentLicenseHeight > rowHeight) {
        rowHeight = componentLicenseHeight;
    }

    PDRectangle rowRectangle = null;
    Color rowColor = Color.WHITE;
    if (isOdd) {
        rowColor = new Color(221, 221, 221);
        rowRectangle = pdfManager.drawRectangle(10, y - rowHeight, pageWidth - 20, rowHeight, rowColor);
    } else {
        rowRectangle = pdfManager.drawRectangle(10, y - rowHeight, pageWidth - 20, rowHeight, rowColor);
    }

    final float rowUpperY = rowRectangle.getUpperRightY();
    if (StringUtils.isNotBlank(component.getPolicyStatus())
            && component.getPolicyStatus().equalsIgnoreCase("IN_VIOLATION")) {
        pdfManager.drawImageCentered(15, rowUpperY, 8, 8, 0, rowHeight,
                "/riskreport/web/images/cross_through_circle.png");
    }
    String componentURL = "";
    if (StringUtils.isNotBlank(component.getComponentURL())) {
        componentURL = component.getComponentURL();
    }
    String componentVersionURL = "";
    if (StringUtils.isNotBlank(component.getComponentVersionURL())) {
        componentVersionURL = component.getComponentVersionURL();
    }
    pdfManager.writeWrappedVerticalCenteredLink(30F, rowUpperY, componentNameWidth, rowHeight,
            componentNameTextLines, componentURL, PDFBoxManager.DEFAULT_COLOR);
    pdfManager.writeWrappedCenteredLink(210, rowUpperY, componentVersionWidth, rowHeight,
            componentVersionTextLines, componentVersionURL, PDFBoxManager.DEFAULT_COLOR);

    final Risk licenseRisk = getLicenseRisk(component, rowColor);

    if (StringUtils.isNotBlank(licenseRisk.riskShortString)) {
        pdfManager.drawRectangleCentered(282, rowUpperY - 1, 12, 12, rowHeight, licenseRisk.riskColor);
        pdfManager.writeTextCentered(282, rowUpperY, rowHeight, licenseRisk.riskShortString);
    }

    pdfManager.writeWrappedVerticalCenteredText(290, rowUpperY, componentLicenseWidth, rowHeight,
            componentLicenseTextLines);

    pdfManager.writeTextCentered(434, rowUpperY, rowHeight,
            String.valueOf(component.getSecurityRiskHighCount()));
    pdfManager.writeTextCentered(477, rowUpperY, rowHeight,
            String.valueOf(component.getSecurityRiskMediumCount()));
    pdfManager.writeTextCentered(520, rowUpperY, rowHeight,
            String.valueOf(component.getSecurityRiskLowCount()));

    final Risk operationalRisk = getOperationalRisk(component, rowColor);

    pdfManager.drawRectangle(545, rowRectangle.getLowerLeftY(), 60, rowHeight, operationalRisk.riskColor);
    pdfManager.writeTextCentered(575, rowUpperY, rowHeight, operationalRisk.riskShortString,
            PDFBoxManager.DEFAULT_FONT_BOLD, 12, PDFBoxManager.DEFAULT_COLOR);

    return rowRectangle;
}

From source file:com.vns.pdf.impl.PdfDocument.java

License:Apache License

private List<Annotation> parseAnnotation(PDPage pdPage) throws IOException {
    List<Annotation> annotations = new ArrayList<>();
    for (PDAnnotation annt : pdPage.getAnnotations()) {
        if (annt instanceof PDAnnotationLink) {
            PDAnnotationLink link = (PDAnnotationLink) annt;
            PDRectangle rect = link.getRectangle();
            float x = rect.getLowerLeftX();
            float y = rect.getUpperRightY();
            float width = rect.getWidth();
            float height = rect.getHeight();
            int rotation = pdPage.getRotation();
            if (rotation == 0) {
                PDRectangle pageSize = pdPage.getMediaBox();
                y = pageSize.getHeight() - y;
            } else if (rotation == 90) {
                //do nothing
            }/*from w w  w.  j a v a2 s  . c  o  m*/

            ActionData actionData = parsePDAction(link.getAction());
            if (actionData == null) {
                actionData = parsePDDestination(link.getDestination());
            }
            if (actionData != null) {
                Annotation a = new Annotation(x, y, width, height, actionData.destX, actionData.destY,
                        actionData.destPage, actionData.destZoom);
                annotations.add(a);
            }
        }
    }
    return annotations;
}

From source file:com.zilbo.flamingSailor.TE.PDFParser.java

License:Apache License

@Override
protected void endPage(PDPage page) throws IOException {
    super.endPage(page);
    int pieceID = 0;
    Map<String, Map<Integer, Long>> fontCounts = new HashMap<>();
    List<TextPiece> wordsOfThisPage = new ArrayList<>();

    for (List<TextPosition> aCharactersByArticle : charactersByArticle) {
        //   int len = aCharactersByArticle.size();
        for (TextPosition t : aCharactersByArticle) {
            // copy information
            TextPiece w = new TextPiece(pieceID++);
            PDFont font = t.getFont();//from w w w .j a  va2 s.co  m
            PDFontDescriptor fontDescriptor = font.getFontDescriptor();

            //   w.setFontDescriptor(fontDescriptor);
            if (fontDescriptor == null) {
                w.setFontName("UNKNOWN");
            } else {
                w.setFontName(fontDescriptor.getFontName());
            }

            /*
            * 100: a simple step to fix the font size to the normal range, for those documents in unknown codes that PDFBox can not process now
            */
            if (t.getFontSize() < 0.3 && t.getYScale() <= 1.0) {
                w.setFontSize(t.getFontSize() * 100);
                w.setHeight(Math.max(t.getYScale(), t.getFontSize()) * 100);
                w.setXScale(t.getXScale());
                w.setYScale(t.getYScale());
            } else {
                if (t.getYScale() < 0.3 && t.getFontSize() <= 1.0) {
                    w.setYScale(t.getYScale() * 100);
                    w.setXScale(t.getXScale() * 100);
                    w.setHeight(Math.max(t.getYScale() * 100, t.getFontSize()));
                } else {
                    w.setFontSize(t.getFontSize());
                    w.setHeight(Math.max(t.getYScale(), t.getFontSize()));
                    w.setXScale(t.getXScale());
                    w.setYScale(t.getYScale());
                }
            }

            Map<Integer, Long> counts = fontCounts.get(w.getFontName());
            if (counts == null) {
                counts = new HashMap<>();
                fontCounts.put(w.getFontName(), counts);
            }
            Long count = counts.get((int) Math.round(w.getHeight()));
            if (count == null) {
                count = 1L;
            } else {
                count += 1L;
            }
            counts.put((int) Math.round(w.getHeight()), count);

            w.setWidth(Math.abs(t.getWidth()));
            w.setGeom(t.getX(), t.getY(), w.getWidth(), w.getHeight());

            w.setText(t.getCharacter());

            w.setWidthOfSpace(t.getWidthOfSpace());
            wordsOfThisPage.add(w);
        }
    }
    currentPage.processPage(wordsOfThisPage, fontCounts);
    currentPage.setText(outString.getBuffer().toString());
    outString.getBuffer().setLength(0);
    List<PDAnnotation> annotations = page.getAnnotations();

    for (PDAnnotation annotation : annotations) {
        if (annotation instanceof PDAnnotationLink) {
            PDAnnotationLink l = (PDAnnotationLink) annotation;
            PDRectangle rect = l.getRectangle();
            PDDestination dest = l.getDestination();
            if (dest instanceof PDPageXYZDestination) {
                PDPageXYZDestination xyzDestination = (PDPageXYZDestination) dest;
                PDPage pageDest = ((PDPageXYZDestination) dest).getPage();

                if (rect != null) {
                    if (xyzDestination.getPageNumber() < 0) {
                        int pageNumber = allpages.indexOf(pageDest) + 1;
                        Rectangle2D hotbox = new Rectangle2D.Double(rect.getLowerLeftX(), rect.getLowerLeftY(),
                                (rect.getUpperRightX() - rect.getLowerLeftX()),
                                (rect.getUpperRightY() - rect.getLowerLeftY()));
                        Point2D toPoint = new Point2D.Double(xyzDestination.getLeft(), xyzDestination.getTop());
                        currentPage.addLink(new PDLink(hotbox, pageNumber, toPoint));
                    }
                }
            }
        }
    }

    /*
     The following code is REALLY raw.
     initial testing seemed to show memory leaks, and was REALLY slow.
            
    PDResources r = page.getResources();
    Map<String, PDXObjectImage> images = r.getImages();
    for (Map.Entry<String, PDXObjectImage> e : images.entrySet()) {
    BufferedImage bi = null;
    try {
            
        //   currentPage.addImage(bi);
            
        //    (e.getValue()).write2file("/tmp/II" + e.getKey());
        if (e.getValue() instanceof PDJpeg) {
            PDJpeg jpg = (PDJpeg) e.getValue();
            bi = jpg.getRGBImage();
            ColorSpace cs = bi.getColorModel().getColorSpace();
            File jpgFile = new File("/tmp/II" + e.getKey() + ".jpg");
            
            if (cs instanceof ColorSpaceCMYK) {
            
                logger.info("Ignoring image with CMYK color space");
            } else {
               // ImageIO.write(bi, "jpg", jpgFile);
                jpg.write2file("/tmp/II"+ e.getKey());
            }
            
        } else {
            (e.getValue()).write2file("/tmp/II" + e.getKey());
        }
    } catch (Exception ee) {
        logger.info("can't read image ;-(", ee);
    }
            
    }
    */

    textPageList.add(currentPage);
    currentPage = null;
}

From source file:de.berber.kindle.annotator.lib.Comment.java

License:Apache License

@Override
protected PDAnnotation toPDAnnotation(final @Nonnull PDDocumentOutline documentOutline,
        final @Nonnull PDPage page) {
    LOG.info("Creating annotation " + xPositionFactor + "/" + yPositionFactor + " -> " + text);

    // Create annotation text with background color
    final PDGamma pdColor = getColor();
    final PDAnnotationText textAnnotation = new PDAnnotationText();
    textAnnotation.setContents(getText());
    textAnnotation.setColour(pdColor);// w w  w . j a va 2s . co  m

    // set the text position
    final PDRectangle cropBox = page.getTrimBox();
    final PDRectangle position = new PDRectangle();
    position.setLowerLeftX((float) (cropBox.getLowerLeftX()
            + xPositionFactor * (cropBox.getUpperRightX() - cropBox.getLowerLeftX())));
    position.setUpperRightX((float) (cropBox.getLowerLeftX()
            + xPositionFactor * (cropBox.getUpperRightX() - cropBox.getLowerLeftX())));

    position.setUpperRightY((float) (cropBox.getUpperRightY()
            - yPositionFactor * (cropBox.getUpperRightY() - cropBox.getLowerLeftY())));
    position.setLowerLeftY((float) (cropBox.getUpperRightY()
            - yPositionFactor * (cropBox.getUpperRightY() - cropBox.getLowerLeftY())));

    textAnnotation.setRectangle(position);

    return textAnnotation;
}