Search in sources :

Example 1 with PDGraphicsState

use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.

the class PageDrawer method endTextClip.

/**
 * End buffering the text clipping path, if any.
 */
private void endTextClip() {
    PDGraphicsState state = getGraphicsState();
    RenderingMode renderingMode = state.getTextState().getRenderingMode();
    // apply the buffered clip as one area
    if (renderingMode.isClip() && !textClippings.isEmpty()) {
        // PDFBOX-4150: this is much faster than using textClippingArea.add(new Area(glyph))
        // https://stackoverflow.com/questions/21519007/fast-union-of-shapes-in-java
        GeneralPath path = new GeneralPath();
        for (Shape shape : textClippings) {
            path.append(shape, false);
        }
        state.intersectClippingPath(path);
        textClippings = new ArrayList<>();
        // PDFBOX-3681: lastClip needs to be reset, because after intersection it is still the same
        // object, thus setClip() would believe that it is cached.
        lastClip = null;
    }
}
Also used : RenderingMode(org.apache.pdfbox.pdmodel.graphics.state.RenderingMode) Shape(java.awt.Shape) GeneralPath(java.awt.geom.GeneralPath) PDGraphicsState(org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState)

Example 2 with PDGraphicsState

use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState 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 3 with PDGraphicsState

use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.

the class PDFStreamEngine method processAnnotation.

/**
 * Process the given annotation with the specified appearance stream.
 *
 * @param annotation The annotation containing the appearance stream to process.
 * @param appearance The appearance stream to process.
 * @throws IOException If there is an error reading or parsing the appearance content stream.
 */
protected void processAnnotation(PDAnnotation annotation, PDAppearanceStream appearance) throws IOException {
    PDResources parent = pushResources(appearance);
    Stack<PDGraphicsState> savedStack = saveGraphicsStack();
    PDRectangle bbox = appearance.getBBox();
    PDRectangle rect = annotation.getRectangle();
    Matrix matrix = appearance.getMatrix();
    // zero-sized rectangles are not valid
    if (rect != null && rect.getWidth() > 0 && rect.getHeight() > 0 && bbox != null) {
        // transformed appearance box  fixme: may be an arbitrary shape
        Rectangle2D transformedBox = bbox.transform(matrix).getBounds2D();
        // compute a matrix which scales and translates the transformed appearance box to align
        // with the edges of the annotation's rectangle
        Matrix a = Matrix.getTranslateInstance(rect.getLowerLeftX(), rect.getLowerLeftY());
        a.concatenate(Matrix.getScaleInstance((float) (rect.getWidth() / transformedBox.getWidth()), (float) (rect.getHeight() / transformedBox.getHeight())));
        a.concatenate(Matrix.getTranslateInstance((float) -transformedBox.getX(), (float) -transformedBox.getY()));
        // Matrix shall be concatenated with A to form a matrix AA that maps from the appearance's
        // coordinate system to the annotation's rectangle in default user space
        // 
        // HOWEVER only the opposite order works for rotated pages with
        // filled fields / annotations that have a matrix in the appearance stream, see PDFBOX-3083
        Matrix aa = Matrix.concatenate(a, matrix);
        // make matrix AA the CTM
        getGraphicsState().setCurrentTransformationMatrix(aa);
        // clip to bounding box
        clipToRect(bbox);
        // needed for patterns in appearance streams, e.g. PDFBOX-2182
        initialMatrix = aa.clone();
        processStreamOperators(appearance);
    }
    restoreGraphicsStack(savedStack);
    popResources(parent);
}
Also used : Matrix(org.apache.pdfbox.util.Matrix) Rectangle2D(java.awt.geom.Rectangle2D) PDResources(org.apache.pdfbox.pdmodel.PDResources) PDRectangle(org.apache.pdfbox.pdmodel.common.PDRectangle) PDGraphicsState(org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState)

Example 4 with PDGraphicsState

use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.

the class PDFStreamEngine method processTransparencyGroup.

/**
 * Processes a transparency group stream.
 * @param group
 * @throws IOException
 */
protected void processTransparencyGroup(PDTransparencyGroup group) throws IOException {
    if (currentPage == null) {
        throw new IllegalStateException("No current page, call " + "#processChildStream(PDContentStream, PDPage) instead");
    }
    PDResources parent = pushResources(group);
    Stack<PDGraphicsState> savedStack = saveGraphicsStack();
    Matrix parentMatrix = initialMatrix;
    // the stream's initial matrix includes the parent CTM, e.g. this allows a scaled form
    initialMatrix = getGraphicsState().getCurrentTransformationMatrix().clone();
    // transform the CTM using the stream's matrix
    getGraphicsState().getCurrentTransformationMatrix().concatenate(group.getMatrix());
    // Before execution of the transparency group XObject’s content stream,
    // the current blend mode in the graphics state shall be initialized to Normal,
    // the current stroking and nonstroking alpha constants to 1.0, and the current soft mask to None.
    getGraphicsState().setBlendMode(BlendMode.NORMAL);
    getGraphicsState().setAlphaConstant(1);
    getGraphicsState().setNonStrokeAlphaConstant(1);
    getGraphicsState().setSoftMask(null);
    // clip to bounding box
    clipToRect(group.getBBox());
    processStreamOperators(group);
    initialMatrix = parentMatrix;
    restoreGraphicsStack(savedStack);
    popResources(parent);
}
Also used : Matrix(org.apache.pdfbox.util.Matrix) PDResources(org.apache.pdfbox.pdmodel.PDResources) PDGraphicsState(org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState)

Example 5 with PDGraphicsState

use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.

the class PDFStreamEngine method processType3Stream.

/**
 * Processes a Type 3 character stream.
 *
 * @param charProc Type 3 character procedure
 * @param textRenderingMatrix the Text Rendering Matrix
 * @throws IOException if there is an error reading or parsing the character content stream.
 */
protected void processType3Stream(PDType3CharProc charProc, Matrix textRenderingMatrix) throws IOException {
    if (currentPage == null) {
        throw new IllegalStateException("No current page, call " + "#processChildStream(PDContentStream, PDPage) instead");
    }
    PDResources parent = pushResources(charProc);
    Stack<PDGraphicsState> savedStack = saveGraphicsStack();
    // replace the CTM with the TRM
    getGraphicsState().setCurrentTransformationMatrix(textRenderingMatrix);
    // transform the CTM using the stream's matrix (this is the FontMatrix)
    getGraphicsState().getCurrentTransformationMatrix().concatenate(charProc.getMatrix());
    // note: we don't clip to the BBox as it is often wrong, see PDFBOX-1917
    // save text matrices (Type 3 stream may contain BT/ET, see PDFBOX-2137)
    Matrix textMatrixOld = textMatrix;
    textMatrix = new Matrix();
    Matrix textLineMatrixOld = textLineMatrix;
    textLineMatrix = new Matrix();
    processStreamOperators(charProc);
    // restore text matrices
    textMatrix = textMatrixOld;
    textLineMatrix = textLineMatrixOld;
    restoreGraphicsStack(savedStack);
    popResources(parent);
}
Also used : Matrix(org.apache.pdfbox.util.Matrix) PDResources(org.apache.pdfbox.pdmodel.PDResources) PDGraphicsState(org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState)

Aggregations

PDGraphicsState (org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState)11 Matrix (org.apache.pdfbox.util.Matrix)7 PDResources (org.apache.pdfbox.pdmodel.PDResources)5 PDRectangle (org.apache.pdfbox.pdmodel.common.PDRectangle)3 Shape (java.awt.Shape)2 Rectangle2D (java.awt.geom.Rectangle2D)2 RenderingMode (org.apache.pdfbox.pdmodel.graphics.state.RenderingMode)2 BasicStroke (java.awt.BasicStroke)1 Paint (java.awt.Paint)1 Point (java.awt.Point)1 TexturePaint (java.awt.TexturePaint)1 GeneralPath (java.awt.geom.GeneralPath)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 TrueTypeFont (org.apache.fontbox.ttf.TrueTypeFont)1 BoundingBox (org.apache.fontbox.util.BoundingBox)1 SetMatrix (org.apache.pdfbox.contentstream.operator.state.SetMatrix)1 COSString (org.apache.pdfbox.cos.COSString)1 PDCIDFont (org.apache.pdfbox.pdmodel.font.PDCIDFont)1