use of com.tom_roush.fontbox.ttf.TrueTypeFont in project PdfBox-Android by TomRoush.
the class LegacyPDFStreamEngine method showGlyph.
/**
* This method was originally written by Ben Litchfield for PDFStreamEngine.
*/
@Override
protected void showGlyph(Matrix textRenderingMatrix, PDFont font, int code, String unicode, Vector displacement) throws IOException {
//
// legacy calculations which were previously in PDFStreamEngine
//
// DO NOT USE THIS CODE UNLESS YOU ARE WORKING WITH PDFTextStripper.
// THIS CODE IS DELIBERATELY INCORRECT
//
PDGraphicsState state = getGraphicsState();
Matrix ctm = state.getCurrentTransformationMatrix();
float fontSize = state.getTextState().getFontSize();
float horizontalScaling = state.getTextState().getHorizontalScaling() / 100f;
Matrix textMatrix = getTextMatrix();
BoundingBox bbox = font.getBoundingBox();
if (bbox.getLowerLeftY() < Short.MIN_VALUE) {
// PDFBOX-2158 and PDFBOX-3130
// files by Salmat eSolutions / ClibPDF Library
bbox.setLowerLeftY(-(bbox.getLowerLeftY() + 65536));
}
// 1/2 the bbox is used as the height todo: why?
float glyphHeight = bbox.getHeight() / 2;
// sometimes the bbox has very high values, but CapHeight is OK
PDFontDescriptor fontDescriptor = font.getFontDescriptor();
if (fontDescriptor != null) {
float capHeight = fontDescriptor.getCapHeight();
if (Float.compare(capHeight, 0) != 0 && (capHeight < glyphHeight || Float.compare(glyphHeight, 0) == 0)) {
glyphHeight = capHeight;
}
// PDFBOX-3464, PDFBOX-4480, PDFBOX-4553:
// sometimes even CapHeight has very high value, but Ascent and Descent are ok
float ascent = fontDescriptor.getAscent();
float descent = fontDescriptor.getDescent();
if (capHeight > ascent && ascent > 0 && descent < 0 && ((ascent - descent) / 2 < glyphHeight || Float.compare(glyphHeight, 0) == 0)) {
glyphHeight = (ascent - descent) / 2;
}
}
// transformPoint from glyph space -> text space
float height;
if (font instanceof PDType3Font) {
height = font.getFontMatrix().transformPoint(0, glyphHeight).y;
} else {
height = glyphHeight / 1000;
}
float displacementX = displacement.getX();
// calculate our own
if (font.isVertical()) {
displacementX = font.getWidth(code) / 1000;
// there may be an additional scaling factor for true type fonts
TrueTypeFont ttf = null;
if (font instanceof PDTrueTypeFont) {
ttf = ((PDTrueTypeFont) font).getTrueTypeFont();
} else if (font instanceof PDType0Font) {
PDCIDFont cidFont = ((PDType0Font) font).getDescendantFont();
if (cidFont instanceof PDCIDFontType2) {
ttf = ((PDCIDFontType2) cidFont).getTrueTypeFont();
}
}
if (ttf != null && ttf.getUnitsPerEm() != 1000) {
displacementX *= 1000f / ttf.getUnitsPerEm();
}
}
//
// legacy calculations which were previously in PDFStreamEngine
//
// DO NOT USE THIS CODE UNLESS YOU ARE WORKING WITH PDFTextStripper.
// THIS CODE IS DELIBERATELY INCORRECT
//
// (modified) combined displacement, this is calculated *without* taking the character
// spacing and word spacing into account, due to legacy code in TextStripper
float tx = displacementX * fontSize * horizontalScaling;
float ty = displacement.getY() * fontSize;
// (modified) combined displacement matrix
Matrix td = Matrix.getTranslateInstance(tx, ty);
// (modified) text rendering matrix
// text space -> device space
Matrix nextTextRenderingMatrix = td.multiply(textMatrix).multiply(ctm);
float nextX = nextTextRenderingMatrix.getTranslateX();
float nextY = nextTextRenderingMatrix.getTranslateY();
// (modified) width and height calculations
float dxDisplay = nextX - textRenderingMatrix.getTranslateX();
float dyDisplay = height * textRenderingMatrix.getScalingFactorY();
//
// start of the original method
//
// Note on variable names. There are three different units being used in this code.
// Character sizes are given in glyph units, text locations are initially given in text
// units, and we want to save the data in display units. The variable names should end with
// Text or Disp to represent if the values are in text or disp units (no glyph units are
// saved).
float glyphSpaceToTextSpaceFactor = 1 / 1000f;
if (font instanceof PDType3Font) {
glyphSpaceToTextSpaceFactor = font.getFontMatrix().getScaleX();
}
float spaceWidthText = 0;
try {
// to avoid crash as described in PDFBOX-614, see what the space displacement should be
spaceWidthText = font.getSpaceWidth() * glyphSpaceToTextSpaceFactor;
} catch (Throwable exception) {
Log.w("PdfBox-Android", exception.getMessage(), exception);
}
if (spaceWidthText == 0) {
spaceWidthText = font.getAverageFontWidth() * glyphSpaceToTextSpaceFactor;
// the average space width appears to be higher than necessary so make it smaller
spaceWidthText *= .80f;
}
if (spaceWidthText == 0) {
// if could not find font, use a generic value
spaceWidthText = 1.0f;
}
// the space width has to be transformed into display units
float spaceWidthDisplay = spaceWidthText * textRenderingMatrix.getScalingFactorX();
// use our additional glyph list for Unicode mapping
unicode = font.toUnicode(code, glyphList);
// this, which is why we leave it until this point in PDFTextStreamEngine.
if (unicode == null) {
if (font instanceof PDSimpleFont) {
char c = (char) code;
unicode = new String(new char[] { c });
} else {
// skips them. See the "allah2.pdf" TestTextStripper file.
return;
}
}
// adjust for cropbox if needed
Matrix translatedTextRenderingMatrix;
if (translateMatrix == null) {
translatedTextRenderingMatrix = textRenderingMatrix;
} else {
translatedTextRenderingMatrix = Matrix.concatenate(translateMatrix, textRenderingMatrix);
nextX -= pageSize.getLowerLeftX();
nextY -= pageSize.getLowerLeftY();
}
processTextPosition(new TextPosition(pageRotation, pageSize.getWidth(), pageSize.getHeight(), translatedTextRenderingMatrix, nextX, nextY, Math.abs(dyDisplay), dxDisplay, Math.abs(spaceWidthDisplay), unicode, new int[] { code }, font, fontSize, (int) (fontSize * textMatrix.getScalingFactorX())));
}
use of com.tom_roush.fontbox.ttf.TrueTypeFont in project PdfBox-Android by TomRoush.
the class TestCMap method testPDFBox3997.
/**
* PDFBOX-3997: test unicode that is above the basic multilingual plane, here: helicopter
* symbol, or D83D DE81 in the Noto Emoji font.
*
* @throws IOException
*/
@Test
public // TODO: PdfBox-Android - provide test file
void testPDFBox3997() throws IOException {
String fontPath = "target/pdfs/NotoEmoji-Regular.ttf";
assumeTrue(new File(fontPath).exists());
TrueTypeFont ttf = new TTFParser().parse(fontPath);
CmapLookup cmap = ttf.getUnicodeCmapLookup(false);
Assert.assertEquals(886, cmap.getGlyphId(0x1F681));
ttf.close();
}
use of com.tom_roush.fontbox.ttf.TrueTypeFont in project PdfBox-Android by TomRoush.
the class PDDocument method close.
/**
* This will close the underlying COSDocument object.
*
* @throws IOException If there is an error releasing resources.
*/
@Override
public void close() throws IOException {
if (!document.isClosed()) {
// Make sure that:
// - first Exception is kept
// - all IO resources are closed
// - there's a way to see which errors occurred
IOException firstException = null;
// close resources and COSWriter
if (signingSupport != null) {
firstException = IOUtils.closeAndLogException(signingSupport, "SigningSupport", firstException);
}
// close all intermediate I/O streams
firstException = IOUtils.closeAndLogException(document, "COSDocument", firstException);
// close the source PDF stream, if we read from one
if (pdfSource != null) {
firstException = IOUtils.closeAndLogException(pdfSource, "RandomAccessRead pdfSource", firstException);
}
// close fonts
for (TrueTypeFont ttf : fontsToClose) {
firstException = IOUtils.closeAndLogException(ttf, "TrueTypeFont", firstException);
}
// rethrow first exception to keep method contract
if (firstException != null) {
throw firstException;
}
}
}
use of com.tom_roush.fontbox.ttf.TrueTypeFont in project PdfBox-Android by TomRoush.
the class FileSystemFontProvider method addTrueTypeCollection.
/**
* Adds a TTC or OTC to the file cache. To reduce memory, the parsed font is not cached.
*/
private void addTrueTypeCollection(final File ttcFile) throws IOException {
TrueTypeCollection ttc = null;
try {
ttc = new TrueTypeCollection(ttcFile);
ttc.processAllFonts(new TrueTypeFontProcessor() {
@Override
public void process(TrueTypeFont ttf) throws IOException {
addTrueTypeFontImpl(ttf, ttcFile);
}
});
} catch (// TTF parser is buggy
NullPointerException e) {
Log.e("PdfBox-Android", "Could not load font file: " + ttcFile, e);
} catch (IOException e) {
Log.e("PdfBox-Android", "Could not load font file: " + ttcFile, e);
} finally {
if (ttc != null) {
ttc.close();
}
}
}
use of com.tom_roush.fontbox.ttf.TrueTypeFont in project PdfBox-Android by TomRoush.
the class FontMapperImpl method getTrueTypeFont.
/**
* Finds a TrueType font with the given PostScript name, or a suitable substitute, or null.
*
* @param fontDescriptor FontDescriptor
*/
@Override
public FontMapping<TrueTypeFont> getTrueTypeFont(String baseFont, PDFontDescriptor fontDescriptor) {
TrueTypeFont ttf = (TrueTypeFont) findFont(FontFormat.TTF, baseFont);
if (ttf != null) {
return new FontMapping<TrueTypeFont>(ttf, false);
} else {
// fallback - todo: i.e. fuzzy match
String fontName = getFallbackFontName(fontDescriptor);
ttf = (TrueTypeFont) findFont(FontFormat.TTF, fontName);
if (ttf == null) {
// we have to return something here as TTFs aren't strictly required on the system
ttf = lastResortFont;
}
return new FontMapping<TrueTypeFont>(ttf, true);
}
}
Aggregations