List of usage examples for org.apache.pdfbox.text TextPosition getHeight
public float getHeight()
From source file:com.repeatability.pdf.PDFTextStripper.java
License:Apache License
/** * This will print the text of the processed page to "output". It will estimate, based on the coordinates of the * text, where newlines and word spacings should be placed. The text will be sorted only if that feature was * enabled.//from w w w. j av a2s .c o m * * @throws IOException If there is an error writing the text. */ protected void writePage() throws IOException { float maxYForLine = MAX_Y_FOR_LINE_RESET_VALUE; float minYTopForLine = MIN_Y_TOP_FOR_LINE_RESET_VALUE; float endOfLastTextX = END_OF_LAST_TEXT_X_RESET_VALUE; float lastWordSpacing = LAST_WORD_SPACING_RESET_VALUE; float maxHeightForLine = MAX_HEIGHT_FOR_LINE_RESET_VALUE; PositionWrapper lastPosition = null; PositionWrapper lastLineStartPosition = null; boolean startOfPage = true; // flag to indicate start of page boolean startOfArticle; if (charactersByArticle.size() > 0) { writePageStart(); } for (List<TextPosition> textList : charactersByArticle) { if (getSortByPosition()) { TextPositionComparator comparator = new TextPositionComparator(); // because the TextPositionComparator is not transitive, but // JDK7+ enforces transitivity on comparators, we need to use // a custom quicksort implementation (which is slower, unfortunately). if (useCustomQuickSort) { QuickSort.sort(textList, comparator); } else { Collections.sort(textList, comparator); } } Iterator<TextPosition> textIter = textList.iterator(); startArticle(); startOfArticle = true; // Now cycle through to print the text. // We queue up a line at a time before we print so that we can convert // the line from presentation form to logical form (if needed). List<LineItem> line = new ArrayList<LineItem>(); textIter = textList.iterator(); // start from the beginning again // PDF files don't always store spaces. We will need to guess where we should add // spaces based on the distances between TextPositions. Historically, this was done // based on the size of the space character provided by the font. In general, this // worked but there were cases where it did not work. Calculating the average character // width and using that as a metric works better in some cases but fails in some cases // where the spacing worked. So we use both. NOTE: Adobe reader also fails on some of // these examples. // Keeps track of the previous average character width float previousAveCharWidth = -1; while (textIter.hasNext()) { TextPosition position = textIter.next(); PositionWrapper current = new PositionWrapper(position); String characterValue = position.getUnicode(); // Resets the average character width when we see a change in font // or a change in the font size if (lastPosition != null && (position.getFont() != lastPosition.getTextPosition().getFont() || position.getFontSize() != lastPosition.getTextPosition().getFontSize())) { previousAveCharWidth = -1; } float positionX; float positionY; float positionWidth; float positionHeight; // If we are sorting, then we need to use the text direction // adjusted coordinates, because they were used in the sorting. if (getSortByPosition()) { positionX = position.getXDirAdj(); positionY = position.getYDirAdj(); positionWidth = position.getWidthDirAdj(); positionHeight = position.getHeightDir(); } else { positionX = position.getX(); positionY = position.getY(); positionWidth = position.getWidth(); positionHeight = position.getHeight(); } // The current amount of characters in a word int wordCharCount = position.getIndividualWidths().length; // Estimate the expected width of the space based on the // space character with some margin. float wordSpacing = position.getWidthOfSpace(); float deltaSpace; if (wordSpacing == 0 || Float.isNaN(wordSpacing)) { deltaSpace = Float.MAX_VALUE; } else { if (lastWordSpacing < 0) { deltaSpace = wordSpacing * getSpacingTolerance(); } else { deltaSpace = (wordSpacing + lastWordSpacing) / 2f * getSpacingTolerance(); } } // Estimate the expected width of the space based on the average character width // with some margin. This calculation does not make a true average (average of // averages) but we found that it gave the best results after numerous experiments. // Based on experiments we also found that .3 worked well. float averageCharWidth; if (previousAveCharWidth < 0) { averageCharWidth = positionWidth / wordCharCount; } else { averageCharWidth = (previousAveCharWidth + positionWidth / wordCharCount) / 2f; } float deltaCharWidth = averageCharWidth * getAverageCharTolerance(); // Compares the values obtained by the average method and the wordSpacing method // and picks the smaller number. float expectedStartOfNextWordX = EXPECTED_START_OF_NEXT_WORD_X_RESET_VALUE; if (endOfLastTextX != END_OF_LAST_TEXT_X_RESET_VALUE) { if (deltaCharWidth > deltaSpace) { expectedStartOfNextWordX = endOfLastTextX + deltaSpace; } else { expectedStartOfNextWordX = endOfLastTextX + deltaCharWidth; } } if (lastPosition != null) { if (startOfArticle) { lastPosition.setArticleStart(); startOfArticle = false; } // RDD - Here we determine whether this text object is on the current // line. We use the lastBaselineFontSize to handle the superscript // case, and the size of the current font to handle the subscript case. // Text must overlap with the last rendered baseline text by at least // a small amount in order to be considered as being on the same line. // XXX BC: In theory, this check should really check if the next char is in // full range seen in this line. This is what I tried to do with minYTopForLine, // but this caused a lot of regression test failures. So, I'm leaving it be for // now if (!overlap(positionY, positionHeight, maxYForLine, maxHeightForLine)) { writeLine(normalize(line)); line.clear(); lastLineStartPosition = handleLineSeparation(current, lastPosition, lastLineStartPosition, maxHeightForLine); expectedStartOfNextWordX = EXPECTED_START_OF_NEXT_WORD_X_RESET_VALUE; maxYForLine = MAX_Y_FOR_LINE_RESET_VALUE; maxHeightForLine = MAX_HEIGHT_FOR_LINE_RESET_VALUE; minYTopForLine = MIN_Y_TOP_FOR_LINE_RESET_VALUE; } // test if our TextPosition starts after a new word would be expected to start if (expectedStartOfNextWordX != EXPECTED_START_OF_NEXT_WORD_X_RESET_VALUE && expectedStartOfNextWordX < positionX && // only bother adding a space if the last character was not a space lastPosition.getTextPosition().getUnicode() != null && !lastPosition.getTextPosition().getUnicode().endsWith(" ")) { line.add(LineItem.getWordSeparator()); } } if (positionY >= maxYForLine) { maxYForLine = positionY; } // RDD - endX is what PDF considers to be the x coordinate of the // end position of the text. We use it in computing our metrics below. endOfLastTextX = positionX + positionWidth; // add it to the list if (characterValue != null) { if (startOfPage && lastPosition == null) { writeParagraphStart();// not sure this is correct for RTL? } line.add(new LineItem(position)); } maxHeightForLine = Math.max(maxHeightForLine, positionHeight); minYTopForLine = Math.min(minYTopForLine, positionY - positionHeight); lastPosition = current; if (startOfPage) { lastPosition.setParagraphStart(); lastPosition.setLineStart(); lastLineStartPosition = lastPosition; startOfPage = false; } lastWordSpacing = wordSpacing; previousAveCharWidth = averageCharWidth; } // print the final line if (line.size() > 0) { writeLine(normalize(line)); writeParagraphEnd(); } endArticle(); } writePageEnd(); }
From source file:com.tekstosense.segmenter.data.Text.java
License:Open Source License
public static Text newFor(TextPosition tp, PDGraphicsState gs, String text) { Text t = new Text(); t.x = tp.getXDirAdj();// w w w.ja v a2s .c o m t.baseline = tp.getYDirAdj(); t.font = tp.getFont(); t.strokeColor = gs.getStrokingColor(); t.nonStrokeColor = gs.getNonStrokingColor(); t.run = tp.getUnicode(); t.width = tp.getWidth(); t.height = tp.getHeight(); t.pointSize = tp.getFontSizeInPt(); t.fontSize = tp.getYScale(); t.tempRun = t.run; // Bump the width by the word spacing for each space in tp. /* for (int i=0; i<tp.getCharacter().length(); i++) { Character c = tp.getCharacter().charAt(i); if (c.equals(" ")) { t.width -= tp.getWidthOfSpace(); t.width += tp.getWordSpacing(); } } */ return t; }
From source file:helper.pdfpreprocessing.pdf.TextHighlight.java
License:Apache License
/** * Computes a series of bounding boxes (PDRectangle) from a list of TextPositions. It will create a new bounding box * if the vertical tolerance is exceeded * * @param positions// ww w .ja v a 2s . c om * @throws IOException */ public List<PDRectangle> getTextBoundingBoxes(final List<TextPosition> positions) { final List<PDRectangle> boundingBoxes = new ArrayList<>(); float lowerLeftX = -1, lowerLeftY = -1, upperRightX = -1, upperRightY = -1; boolean first = true; for (final TextPosition position : positions) { if (position == null) { continue; } final Matrix textPos = position.getTextMatrix(); final float height = position.getHeight() * getHeightModifier(); if (first) { lowerLeftX = textPos.getTranslateX(); upperRightX = lowerLeftX + position.getWidth(); lowerLeftY = textPos.getTranslateY(); upperRightY = lowerLeftY + height; first = false; continue; } // we are still on the same line if (Math.abs(textPos.getTranslateY() - lowerLeftY) <= getVerticalTolerance()) { upperRightX = textPos.getTranslateX() + position.getWidth(); upperRightY = textPos.getTranslateY() + height; } else { final PDRectangle boundingBox = boundingBox(lowerLeftX, lowerLeftY, upperRightX, upperRightY); boundingBoxes.add(boundingBox); // new line lowerLeftX = textPos.getTranslateX(); upperRightX = lowerLeftX + position.getWidth(); lowerLeftY = textPos.getTranslateY(); upperRightY = lowerLeftY + height; } } if (!(lowerLeftX == -1 && lowerLeftY == -1 && upperRightX == -1 && upperRightY == -1)) { final PDRectangle boundingBox = boundingBox(lowerLeftX, lowerLeftY, upperRightX, upperRightY); boundingBoxes.add(boundingBox); } return boundingBoxes; }
From source file:org.fit.pdfdom.PDFBoxTree.java
License:Open Source License
/** * Updates the text style according to a new text position * @param bstyle the style to be updated * @param text the text position//from w ww . j ava2s. c om */ protected void updateStyle(BoxStyle bstyle, TextPosition text) { String font = text.getFont().getName(); String family = null; String weight = null; String fstyle = null; bstyle.setFontSize(text.getFontSizeInPt()); bstyle.setLineHeight(text.getHeight()); if (font != null) { //font style and weight for (int i = 0; i < pdFontType.length; i++) { if (font.toLowerCase().lastIndexOf(pdFontType[i]) >= 0) { weight = cssFontWeight[i]; fstyle = cssFontStyle[i]; break; } } if (weight != null) bstyle.setFontWeight(weight); else bstyle.setFontWeight(cssFontWeight[0]); if (fstyle != null) bstyle.setFontStyle(fstyle); else bstyle.setFontStyle(cssFontStyle[0]); //font family //If it's a known common font don't embed in html output to save space String knownFontFamily = findKnownFontFamily(font); if (!knownFontFamily.equals("")) family = knownFontFamily; else { family = fontTable.getUsedName(font); if (family == null) family = font; } if (family != null) bstyle.setFontFamily(family); } updateStyleForRenderingMode(); }