Search in sources :

Example 1 with PDTrueTypeFont

use of org.apache.pdfbox.pdmodel.font.PDTrueTypeFont in project pdfbox by apache.

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;
        }
    }
    // 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 (Exception exception) {
        LOG.warn(exception, exception);
    }
    if (Float.compare(spaceWidthText, 0) == 0) {
        spaceWidthText = font.getAverageFontWidth() * glyphSpaceToTextSpaceFactor;
        // the average space width appears to be higher than necessary so make it smaller
        spaceWidthText *= .80f;
    }
    if (Float.compare(spaceWidthText, 0) == 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())));
}
Also used : PDTrueTypeFont(org.apache.pdfbox.pdmodel.font.PDTrueTypeFont) TrueTypeFont(org.apache.fontbox.ttf.TrueTypeFont) PDType0Font(org.apache.pdfbox.pdmodel.font.PDType0Font) PDFontDescriptor(org.apache.pdfbox.pdmodel.font.PDFontDescriptor) IOException(java.io.IOException) PDSimpleFont(org.apache.pdfbox.pdmodel.font.PDSimpleFont) SetMatrix(org.apache.pdfbox.contentstream.operator.state.SetMatrix) Matrix(org.apache.pdfbox.util.Matrix) PDType3Font(org.apache.pdfbox.pdmodel.font.PDType3Font) BoundingBox(org.apache.fontbox.util.BoundingBox) PDTrueTypeFont(org.apache.pdfbox.pdmodel.font.PDTrueTypeFont) PDCIDFontType2(org.apache.pdfbox.pdmodel.font.PDCIDFontType2) PDCIDFont(org.apache.pdfbox.pdmodel.font.PDCIDFont) PDGraphicsState(org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState)

Example 2 with PDTrueTypeFont

use of org.apache.pdfbox.pdmodel.font.PDTrueTypeFont in project pdfbox by apache.

the class ExtractTTFFonts method processResources.

private void processResources(PDResources resources, String prefix, boolean addKey) throws IOException {
    if (resources == null) {
        return;
    }
    for (COSName key : resources.getFontNames()) {
        PDFont font = resources.getFont(key);
        // write the font
        if (font instanceof PDTrueTypeFont) {
            String name;
            if (addKey) {
                name = getUniqueFileName(prefix + "_" + key, "ttf");
            } else {
                name = getUniqueFileName(prefix, "ttf");
            }
            writeFont(font.getFontDescriptor(), name);
        } else if (font instanceof PDType0Font) {
            PDCIDFont descendantFont = ((PDType0Font) font).getDescendantFont();
            if (descendantFont instanceof PDCIDFontType2) {
                String name;
                if (addKey) {
                    name = getUniqueFileName(prefix + "_" + key, "ttf");
                } else {
                    name = getUniqueFileName(prefix, "ttf");
                }
                writeFont(descendantFont.getFontDescriptor(), name);
            }
        }
    }
    for (COSName name : resources.getXObjectNames()) {
        PDXObject xobject = resources.getXObject(name);
        if (xobject instanceof PDFormXObject) {
            PDFormXObject xObjectForm = (PDFormXObject) xobject;
            PDResources formResources = xObjectForm.getResources();
            processResources(formResources, prefix, addKey);
        }
    }
}
Also used : PDFont(org.apache.pdfbox.pdmodel.font.PDFont) COSName(org.apache.pdfbox.cos.COSName) PDType0Font(org.apache.pdfbox.pdmodel.font.PDType0Font) PDTrueTypeFont(org.apache.pdfbox.pdmodel.font.PDTrueTypeFont) PDFormXObject(org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject) PDResources(org.apache.pdfbox.pdmodel.PDResources) PDCIDFontType2(org.apache.pdfbox.pdmodel.font.PDCIDFontType2) PDCIDFont(org.apache.pdfbox.pdmodel.font.PDCIDFont) PDXObject(org.apache.pdfbox.pdmodel.graphics.PDXObject)

Example 3 with PDTrueTypeFont

use of org.apache.pdfbox.pdmodel.font.PDTrueTypeFont in project pdfbox by apache.

the class TrueTypeFontValidator method checkEncoding.

@Override
protected void checkEncoding() {
    PDTrueTypeFont ttFont = (PDTrueTypeFont) font;
    PDFontDescriptor fd = ttFont.getFontDescriptor();
    if (fd != null) {
        /*
             * only MacRomanEncoding or WinAnsiEncoding are allowed for a non symbolic font.
             */
        if (fd.isNonSymbolic()) {
            Encoding encodingValue = ttFont.getEncoding();
            if (!(encodingValue instanceof MacRomanEncoding || encodingValue instanceof WinAnsiEncoding)) {
                this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING, fd.getFontName() + ": The Encoding is invalid for the NonSymbolic TTF"));
            }
        }
        /*
             * For symbolic font, no encoding entry is allowed and only one encoding entry is expected into the FontFile
             * CMap (Check latter when the FontFile stream will be checked)
             */
        if (fd.isSymbolic() && fontDictionary.getItem(COSName.ENCODING) != null) {
            this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING, fd.getFontName() + ": The Encoding should be missing for the Symbolic TTF"));
        }
    }
}
Also used : PDTrueTypeFont(org.apache.pdfbox.pdmodel.font.PDTrueTypeFont) Encoding(org.apache.pdfbox.pdmodel.font.encoding.Encoding) MacRomanEncoding(org.apache.pdfbox.pdmodel.font.encoding.MacRomanEncoding) WinAnsiEncoding(org.apache.pdfbox.pdmodel.font.encoding.WinAnsiEncoding) MacRomanEncoding(org.apache.pdfbox.pdmodel.font.encoding.MacRomanEncoding) ValidationError(org.apache.pdfbox.preflight.ValidationResult.ValidationError) WinAnsiEncoding(org.apache.pdfbox.pdmodel.font.encoding.WinAnsiEncoding) PDFontDescriptor(org.apache.pdfbox.pdmodel.font.PDFontDescriptor)

Example 4 with PDTrueTypeFont

use of org.apache.pdfbox.pdmodel.font.PDTrueTypeFont in project pdfbox by apache.

the class DrawPrintTextLocations method calculateGlyphBounds.

// this calculates the real (except for type 3 fonts) individual glyph bounds
private Shape calculateGlyphBounds(Matrix textRenderingMatrix, PDFont font, int code) throws IOException {
    GeneralPath path = null;
    AffineTransform at = textRenderingMatrix.createAffineTransform();
    at.concatenate(font.getFontMatrix().createAffineTransform());
    if (font instanceof PDType3Font) {
        // It is difficult to calculate the real individual glyph bounds for type 3 fonts
        // because these are not vector fonts, the content stream could contain almost anything
        // that is found in page content streams.
        PDType3Font t3Font = (PDType3Font) font;
        PDType3CharProc charProc = t3Font.getCharProc(code);
        if (charProc != null) {
            BoundingBox fontBBox = t3Font.getBoundingBox();
            PDRectangle glyphBBox = charProc.getGlyphBBox();
            if (glyphBBox != null) {
                // PDFBOX-3850: glyph bbox could be larger than the font bbox
                glyphBBox.setLowerLeftX(Math.max(fontBBox.getLowerLeftX(), glyphBBox.getLowerLeftX()));
                glyphBBox.setLowerLeftY(Math.max(fontBBox.getLowerLeftY(), glyphBBox.getLowerLeftY()));
                glyphBBox.setUpperRightX(Math.min(fontBBox.getUpperRightX(), glyphBBox.getUpperRightX()));
                glyphBBox.setUpperRightY(Math.min(fontBBox.getUpperRightY(), glyphBBox.getUpperRightY()));
                path = glyphBBox.toGeneralPath();
            }
        }
    } else if (font instanceof PDVectorFont) {
        PDVectorFont vectorFont = (PDVectorFont) font;
        path = vectorFont.getPath(code);
        if (font instanceof PDTrueTypeFont) {
            PDTrueTypeFont ttFont = (PDTrueTypeFont) font;
            int unitsPerEm = ttFont.getTrueTypeFont().getHeader().getUnitsPerEm();
            at.scale(1000d / unitsPerEm, 1000d / unitsPerEm);
        }
        if (font instanceof PDType0Font) {
            PDType0Font t0font = (PDType0Font) font;
            if (t0font.getDescendantFont() instanceof PDCIDFontType2) {
                int unitsPerEm = ((PDCIDFontType2) t0font.getDescendantFont()).getTrueTypeFont().getHeader().getUnitsPerEm();
                at.scale(1000d / unitsPerEm, 1000d / unitsPerEm);
            }
        }
    } else if (font instanceof PDSimpleFont) {
        PDSimpleFont simpleFont = (PDSimpleFont) font;
        // these two lines do not always work, e.g. for the TT fonts in file 032431.pdf
        // which is why PDVectorFont is tried first.
        String name = simpleFont.getEncoding().getName(code);
        path = simpleFont.getPath(name);
    } else {
        // shouldn't happen, please open issue in JIRA
        System.out.println("Unknown font class: " + font.getClass());
    }
    if (path == null) {
        return null;
    }
    return at.createTransformedShape(path.getBounds2D());
}
Also used : PDType3CharProc(org.apache.pdfbox.pdmodel.font.PDType3CharProc) GeneralPath(java.awt.geom.GeneralPath) PDType3Font(org.apache.pdfbox.pdmodel.font.PDType3Font) PDType0Font(org.apache.pdfbox.pdmodel.font.PDType0Font) BoundingBox(org.apache.fontbox.util.BoundingBox) PDTrueTypeFont(org.apache.pdfbox.pdmodel.font.PDTrueTypeFont) AffineTransform(java.awt.geom.AffineTransform) PDRectangle(org.apache.pdfbox.pdmodel.common.PDRectangle) PDCIDFontType2(org.apache.pdfbox.pdmodel.font.PDCIDFontType2) PDVectorFont(org.apache.pdfbox.pdmodel.font.PDVectorFont) PDSimpleFont(org.apache.pdfbox.pdmodel.font.PDSimpleFont)

Aggregations

PDTrueTypeFont (org.apache.pdfbox.pdmodel.font.PDTrueTypeFont)4 PDCIDFontType2 (org.apache.pdfbox.pdmodel.font.PDCIDFontType2)3 PDType0Font (org.apache.pdfbox.pdmodel.font.PDType0Font)3 BoundingBox (org.apache.fontbox.util.BoundingBox)2 PDCIDFont (org.apache.pdfbox.pdmodel.font.PDCIDFont)2 PDFontDescriptor (org.apache.pdfbox.pdmodel.font.PDFontDescriptor)2 PDSimpleFont (org.apache.pdfbox.pdmodel.font.PDSimpleFont)2 PDType3Font (org.apache.pdfbox.pdmodel.font.PDType3Font)2 AffineTransform (java.awt.geom.AffineTransform)1 GeneralPath (java.awt.geom.GeneralPath)1 IOException (java.io.IOException)1 TrueTypeFont (org.apache.fontbox.ttf.TrueTypeFont)1 SetMatrix (org.apache.pdfbox.contentstream.operator.state.SetMatrix)1 COSName (org.apache.pdfbox.cos.COSName)1 PDResources (org.apache.pdfbox.pdmodel.PDResources)1 PDRectangle (org.apache.pdfbox.pdmodel.common.PDRectangle)1 PDFont (org.apache.pdfbox.pdmodel.font.PDFont)1 PDType3CharProc (org.apache.pdfbox.pdmodel.font.PDType3CharProc)1 PDVectorFont (org.apache.pdfbox.pdmodel.font.PDVectorFont)1 Encoding (org.apache.pdfbox.pdmodel.font.encoding.Encoding)1