use of com.tom_roush.pdfbox.pdmodel.common.PDRectangle in project PdfBox-Android by TomRoush.
the class PDType3CharProc method getGlyphBBox.
/**
* Calculate the bounding box of this glyph. This will work only if the first operator in the
* stream is d1.
*
* @return the bounding box of this glyph, or null if the first operator is not d1.
* @throws IOException If an io error occurs while parsing the stream.
*/
public PDRectangle getGlyphBBox() throws IOException {
List<COSBase> arguments = new ArrayList<COSBase>();
PDFStreamParser parser = new PDFStreamParser(this);
Object token = parser.parseNextToken();
while (token != null) {
if (token instanceof COSObject) {
arguments.add(((COSObject) token).getObject());
} else if (token instanceof Operator) {
if (((Operator) token).getName().equals("d1") && arguments.size() == 6) {
for (int i = 0; i < 6; ++i) {
if (!(arguments.get(i) instanceof COSNumber)) {
return null;
}
}
return new PDRectangle(((COSNumber) arguments.get(2)).floatValue(), ((COSNumber) arguments.get(3)).floatValue(), ((COSNumber) arguments.get(4)).floatValue() - ((COSNumber) arguments.get(2)).floatValue(), ((COSNumber) arguments.get(5)).floatValue() - ((COSNumber) arguments.get(3)).floatValue());
} else {
return null;
}
} else {
arguments.add((COSBase) token);
}
token = parser.parseNextToken();
}
return null;
}
use of com.tom_roush.pdfbox.pdmodel.common.PDRectangle in project PdfBox-Android by TomRoush.
the class PDType3Font method getFontBBox.
/**
* This will get the fonts bounding box from its dictionary.
*
* @return The fonts bounding box.
*/
public PDRectangle getFontBBox() {
COSBase base = dict.getDictionaryObject(COSName.FONT_BBOX);
PDRectangle retval = null;
if (base instanceof COSArray) {
retval = new PDRectangle((COSArray) base);
}
return retval;
}
use of com.tom_roush.pdfbox.pdmodel.common.PDRectangle in project PdfBox-Android by TomRoush.
the class TrueTypeEmbedder method createFontDescriptor.
/**
* Creates a new font descriptor dictionary for the given TTF.
*/
private PDFontDescriptor createFontDescriptor(TrueTypeFont ttf) throws IOException {
PDFontDescriptor fd = new PDFontDescriptor();
fd.setFontName(ttf.getName());
OS2WindowsMetricsTable os2 = ttf.getOS2Windows();
PostScriptTable post = ttf.getPostScript();
// Flags
fd.setFixedPitch(post.getIsFixedPitch() > 0 || ttf.getHorizontalHeader().getNumberOfHMetrics() == 1);
int fsSelection = os2.getFsSelection();
fd.setItalic(((fsSelection & (ITALIC | OBLIQUE)) != 0));
switch(os2.getFamilyClass()) {
case OS2WindowsMetricsTable.FAMILY_CLASS_CLAREDON_SERIFS:
case OS2WindowsMetricsTable.FAMILY_CLASS_FREEFORM_SERIFS:
case OS2WindowsMetricsTable.FAMILY_CLASS_MODERN_SERIFS:
case OS2WindowsMetricsTable.FAMILY_CLASS_OLDSTYLE_SERIFS:
case OS2WindowsMetricsTable.FAMILY_CLASS_SLAB_SERIFS:
fd.setSerif(true);
break;
case OS2WindowsMetricsTable.FAMILY_CLASS_SCRIPTS:
fd.setScript(true);
break;
default:
break;
}
fd.setFontWeight(os2.getWeightClass());
fd.setSymbolic(true);
fd.setNonSymbolic(false);
// ItalicAngle
fd.setItalicAngle(post.getItalicAngle());
// FontBBox
HeaderTable header = ttf.getHeader();
PDRectangle rect = new PDRectangle();
float scaling = 1000f / header.getUnitsPerEm();
rect.setLowerLeftX(header.getXMin() * scaling);
rect.setLowerLeftY(header.getYMin() * scaling);
rect.setUpperRightX(header.getXMax() * scaling);
rect.setUpperRightY(header.getYMax() * scaling);
fd.setFontBoundingBox(rect);
// Ascent, Descent
HorizontalHeaderTable hHeader = ttf.getHorizontalHeader();
fd.setAscent(hHeader.getAscender() * scaling);
fd.setDescent(hHeader.getDescender() * scaling);
// CapHeight, XHeight
if (os2.getVersion() >= 1.2) {
fd.setCapHeight(os2.getCapHeight() * scaling);
fd.setXHeight(os2.getHeight() * scaling);
} else {
Path capHPath = ttf.getPath("H");
if (capHPath != null) {
RectF capHPathBounds = new RectF();
capHPath.computeBounds(capHPathBounds, true);
fd.setCapHeight(Math.round(capHPathBounds.bottom) * scaling);
} else {
// estimate by summing the typographical +ve ascender and -ve descender
fd.setCapHeight((os2.getTypoAscender() + os2.getTypoDescender()) * scaling);
}
Path xPath = ttf.getPath("x");
if (xPath != null) {
RectF xPathBounds = new RectF();
xPath.computeBounds(xPathBounds, true);
fd.setXHeight(Math.round(xPathBounds.bottom) * scaling);
} else {
// estimate by halving the typographical ascender
fd.setXHeight(os2.getTypoAscender() / 2.0f * scaling);
}
}
// StemV - there's no true TTF equivalent of this, so we estimate it
fd.setStemV(fd.getFontBoundingBox().getWidth() * .13f);
return fd;
}
use of com.tom_roush.pdfbox.pdmodel.common.PDRectangle in project PdfBox-Android by TomRoush.
the class PageDrawer method showAnnotation.
@Override
public void showAnnotation(PDAnnotation annotation) throws IOException {
lastClip = null;
// Device checks shouldn't be needed
if (annotation.isNoView()) {
return;
}
if (annotation.isHidden()) {
return;
}
if (annotation.isInvisible() && annotation instanceof PDAnnotationUnknown) {
// of the standard annotation types and no annotation handler is available."
return;
}
if (isHiddenOCG(annotation.getOptionalContent())) {
return;
}
PDAppearanceDictionary appearance = annotation.getAppearance();
if (appearance == null || appearance.getNormalAppearance() == null) {
annotation.constructAppearances(renderer.document);
}
if (annotation.isNoRotate() && getCurrentPage().getRotation() != 0) {
PDRectangle rect = annotation.getRectangle();
android.graphics.Matrix savedTransform = canvas.getMatrix();
// "The upper-left corner of the annotation remains at the same point in
// default user space; the annotation pivots around that point."
canvas.rotate(getCurrentPage().getRotation(), rect.getLowerLeftX(), rect.getUpperRightY());
super.showAnnotation(annotation);
canvas.setMatrix(savedTransform);
} else {
super.showAnnotation(annotation);
}
}
use of com.tom_roush.pdfbox.pdmodel.common.PDRectangle in project PdfBox-Android by TomRoush.
the class PDFTextStripper method processTextPosition.
/**
* This will process a TextPosition object and add the text to the list of characters on a page. It takes care of
* overlapping text.
*
* @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);
// 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);
} else // one and remove it from the list.
if (previousTextPosition.isDiacritic() && text.contains(previousTextPosition)) {
text.mergeDiacritic(previousTextPosition);
textList.remove(textList.size() - 1);
textList.add(text);
} else {
textList.add(text);
}
}
}
}
Aggregations