Search in sources :

Example 1 with PDType3Font

use of org.apache.pdfbox.pdmodel.font.PDType3Font 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 PDType3Font

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

the class DrawPrintTextLocations method writeString.

/**
 * Override the default functionality of PDFTextStripper.
 */
@Override
protected void writeString(String string, List<TextPosition> textPositions) throws IOException {
    for (TextPosition text : textPositions) {
        System.out.println("String[" + text.getXDirAdj() + "," + text.getYDirAdj() + " fs=" + text.getFontSize() + " xscale=" + text.getXScale() + " height=" + text.getHeightDir() + " space=" + text.getWidthOfSpace() + " width=" + text.getWidthDirAdj() + "]" + text.getUnicode());
        // glyph space -> user space
        // note: text.getTextMatrix() is *not* the Text Matrix, it's the Text Rendering Matrix
        AffineTransform at = text.getTextMatrix().createAffineTransform();
        // in red:
        // show rectangles with the "height" (not a real height, but used for text extraction
        // heuristics, it is 1/2 of the bounding box height and starts at y=0)
        Rectangle2D.Float rect = new Rectangle2D.Float(0, 0, text.getWidthDirAdj() / text.getTextMatrix().getScalingFactorX(), text.getHeightDir() / text.getTextMatrix().getScalingFactorY());
        Shape s = at.createTransformedShape(rect);
        s = flipAT.createTransformedShape(s);
        s = rotateAT.createTransformedShape(s);
        g2d.setColor(Color.red);
        g2d.draw(s);
        // in blue:
        // show rectangle with the real vertical bounds, based on the font bounding box y values
        // usually, the height is identical to what you see when marking text in Adobe Reader
        PDFont font = text.getFont();
        BoundingBox bbox = font.getBoundingBox();
        // advance width, bbox height (glyph space)
        // todo: should iterate all chars
        float xadvance = font.getWidth(text.getCharacterCodes()[0]);
        rect = new Rectangle2D.Float(0, bbox.getLowerLeftY(), xadvance, bbox.getHeight());
        if (font instanceof PDType3Font) {
            // bbox and font matrix are unscaled
            at.concatenate(font.getFontMatrix().createAffineTransform());
        } else {
            // bbox and font matrix are already scaled to 1000
            at.scale(1 / 1000f, 1 / 1000f);
        }
        s = at.createTransformedShape(rect);
        s = flipAT.createTransformedShape(s);
        s = rotateAT.createTransformedShape(s);
        g2d.setColor(Color.blue);
        g2d.draw(s);
    }
}
Also used : PDFont(org.apache.pdfbox.pdmodel.font.PDFont) Shape(java.awt.Shape) PDType3Font(org.apache.pdfbox.pdmodel.font.PDType3Font) TextPosition(org.apache.pdfbox.text.TextPosition) BoundingBox(org.apache.fontbox.util.BoundingBox) Rectangle2D(java.awt.geom.Rectangle2D) AffineTransform(java.awt.geom.AffineTransform)

Example 3 with PDType3Font

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

the class DebugPageDrawer method showGlyph.

/**
 * Glyph bounding boxes.
 */
@Override
protected void showGlyph(Matrix textRenderingMatrix, PDFont font, int code, String unicode, Vector displacement) throws IOException {
    // draw glyph
    super.showGlyph(textRenderingMatrix, font, code, unicode, displacement);
    if (showGlyphBounds) {
        Shape bbox;
        // compute visual bounds
        if (font instanceof PDType3Font) {
            // todo: implement me
            return;
        } else {
            AffineTransform at = textRenderingMatrix.createAffineTransform();
            at.concatenate(font.getFontMatrix().createAffineTransform());
            // get the path
            PDVectorFont vectorFont = (PDVectorFont) font;
            GeneralPath path = vectorFont.getNormalizedPath(code);
            if (path == null) {
                return;
            }
            // stretch non-embedded glyph if it does not match the width contained in the PDF
            if (!font.isEmbedded() && !font.isVertical() && !font.isStandard14() && font.hasExplicitWidth(code)) {
                float fontWidth = font.getWidthFromFont(code);
                if (// ignore spaces
                fontWidth > 0 && Math.abs(fontWidth - displacement.getX() * 1000) > 0.0001) {
                    float pdfWidth = displacement.getX() * 1000;
                    at.scale(pdfWidth / fontWidth, 1);
                }
            }
            Shape glyph = at.createTransformedShape(path);
            bbox = glyph.getBounds2D();
        }
        // save
        Graphics2D graphics = getGraphics();
        Color color = graphics.getColor();
        Stroke stroke = graphics.getStroke();
        Shape clip = graphics.getClip();
        // draw
        graphics.setClip(graphics.getDeviceConfiguration().getBounds());
        graphics.setColor(Color.cyan);
        graphics.setStroke(new BasicStroke(.5f));
        graphics.draw(bbox);
        // restore
        graphics.setStroke(stroke);
        graphics.setColor(color);
        graphics.setClip(clip);
    }
}
Also used : BasicStroke(java.awt.BasicStroke) Stroke(java.awt.Stroke) BasicStroke(java.awt.BasicStroke) Shape(java.awt.Shape) PDType3Font(org.apache.pdfbox.pdmodel.font.PDType3Font) GeneralPath(java.awt.geom.GeneralPath) Color(java.awt.Color) AffineTransform(java.awt.geom.AffineTransform) PDVectorFont(org.apache.pdfbox.pdmodel.font.PDVectorFont) Graphics2D(java.awt.Graphics2D)

Example 4 with PDType3Font

use of org.apache.pdfbox.pdmodel.font.PDType3Font 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

PDType3Font (org.apache.pdfbox.pdmodel.font.PDType3Font)4 AffineTransform (java.awt.geom.AffineTransform)3 BoundingBox (org.apache.fontbox.util.BoundingBox)3 Shape (java.awt.Shape)2 GeneralPath (java.awt.geom.GeneralPath)2 PDCIDFontType2 (org.apache.pdfbox.pdmodel.font.PDCIDFontType2)2 PDSimpleFont (org.apache.pdfbox.pdmodel.font.PDSimpleFont)2 PDTrueTypeFont (org.apache.pdfbox.pdmodel.font.PDTrueTypeFont)2 PDType0Font (org.apache.pdfbox.pdmodel.font.PDType0Font)2 PDVectorFont (org.apache.pdfbox.pdmodel.font.PDVectorFont)2 BasicStroke (java.awt.BasicStroke)1 Color (java.awt.Color)1 Graphics2D (java.awt.Graphics2D)1 Stroke (java.awt.Stroke)1 Rectangle2D (java.awt.geom.Rectangle2D)1 IOException (java.io.IOException)1 TrueTypeFont (org.apache.fontbox.ttf.TrueTypeFont)1 SetMatrix (org.apache.pdfbox.contentstream.operator.state.SetMatrix)1 PDRectangle (org.apache.pdfbox.pdmodel.common.PDRectangle)1 PDCIDFont (org.apache.pdfbox.pdmodel.font.PDCIDFont)1