org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState Java Examples

The following examples show how to use org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PageDrawer.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
/**
 * 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<Shape>();

        // 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;
    }
}
 
Example #2
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
/**
 * Process a content stream.
 *
 * @param contentStream the content stream
 * @throws IOException if there is an exception while processing the stream
 */
private void processStream(PDContentStream contentStream) throws IOException
{
    PDResources parent = pushResources(contentStream);
    Deque<PDGraphicsState> savedStack = saveGraphicsStack();
    Matrix parentMatrix = initialMatrix;

    // transform the CTM using the stream's matrix
    getGraphicsState().getCurrentTransformationMatrix().concatenate(contentStream.getMatrix());

    // the stream's initial matrix includes the parent CTM, e.g. this allows a scaled form
    initialMatrix = getGraphicsState().getCurrentTransformationMatrix().clone();

    // clip to bounding box
    PDRectangle bbox = contentStream.getBBox();
    clipToRect(bbox);

    processStreamOperators(contentStream);

    initialMatrix = parentMatrix;
    restoreGraphicsStack(savedStack);
    popResources(parent);
}
 
Example #3
Source File: PageDrawer.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
@Override
protected void showType3Glyph(Matrix textRenderingMatrix, PDType3Font font, int code,
        String unicode, Vector displacement) throws IOException
{
    PDGraphicsState state = getGraphicsState();
    RenderingMode renderingMode = state.getTextState().getRenderingMode();
    if (!RenderingMode.NEITHER.equals(renderingMode))
    {
        super.showType3Glyph(textRenderingMatrix, font, code, unicode, displacement);
    }
}
 
Example #4
Source File: PageDrawer.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
private BasicStroke getStroke()
{
    PDGraphicsState state = getGraphicsState();

    // apply the CTM
    float lineWidth = transformWidth(state.getLineWidth());

    // minimum line width as used by Adobe Reader
    if (lineWidth < 0.25)
    {
        lineWidth = 0.25f;
    }

    PDLineDashPattern dashPattern = state.getLineDashPattern();
    float phaseStart = dashPattern.getPhase();
    float[] dashArray = getDashArray(dashPattern);
    phaseStart = transformWidth(phaseStart);

    // empty dash array is illegal
    // avoid also infinite and NaN values (PDFBOX-3360)
    if (dashArray.length == 0 || Float.isInfinite(phaseStart) || Float.isNaN(phaseStart))
    {
        dashArray = null;
    }
    else
    {
        for (int i = 0; i < dashArray.length; ++i)
        {
            if (Float.isInfinite(dashArray[i]) || Float.isNaN(dashArray[i]))
            {
                dashArray = null;
                break;
            }
        }
    }
    int lineCap = Math.min(2, Math.max(0, state.getLineCap()));
    int lineJoin = Math.min(2, Math.max(0, state.getLineJoin()));
    return new BasicStroke(lineWidth, lineCap, lineJoin,
                           state.getMiterLimit(), dashArray, phaseStart);
}
 
Example #5
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Initializes the stream engine for the given page.
 */
private void initPage(PDPage page)
{
    if (page == null)
    {
        throw new IllegalArgumentException("Page cannot be null");
    }
    currentPage = page;
    graphicsStack.clear();
    graphicsStack.push(new PDGraphicsState(page.getCropBox()));
    textMatrix = null;
    textLineMatrix = null;
    resources = null;
    initialMatrix = page.getMatrix();
}
 
Example #6
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Processes a transparency group stream.
 * 
 * @param group the transparency 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);
    Deque<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);
}
 
Example #7
Source File: PDFVisibleTextStripper.java    From testarea-pdfbox2 with Apache License 2.0 5 votes vote down vote up
@Override
protected void processTextPosition(TextPosition text) {
    Matrix textMatrix = text.getTextMatrix();
    Vector start = textMatrix.transform(new Vector(0, 0));
    Vector end = new Vector(start.getX() + text.getWidth(), start.getY());

    PDGraphicsState gs = getGraphicsState();
    Area area = gs.getCurrentClippingPath();
    if (area == null ||
            (contains(area, lowerLeftX + start.getX(), lowerLeftY + start.getY()) &&
                    ((!checkEndPointToo) || contains(area, lowerLeftX + end.getX(), lowerLeftY + end.getY()))))
        super.processTextPosition(text);
    else if (dropStream != null)
        dropStream.printf("Clipped '%s' at %s,%s\n", text.getUnicode(), lowerLeftX + start.getX(), lowerLeftY + start.getY());
}
 
Example #8
Source File: PdfToTextInfoConverter.java    From testarea-pdfbox2 with Apache License 2.0 5 votes vote down vote up
@Override
public void process(Operator operator, List<COSBase> operands) throws IOException {
    PDGraphicsState gs = getGraphicsState();

    linePath.setWindingRule(GeneralPath.WIND_NON_ZERO);
    addFillPath(gs.getNonStrokingColor());
    linePath.reset();
}
 
Example #9
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Saves the entire graphics stack.
 * 
 * @return the saved graphics state stack.
 */
protected final Deque<PDGraphicsState> saveGraphicsStack()
{
    Deque<PDGraphicsState> savedStack = graphicsStack;
    graphicsStack = new ArrayDeque<PDGraphicsState>();
    graphicsStack.add(savedStack.peek().clone());
    return savedStack;
}
 
Example #10
Source File: PdfToTextInfoConverter.java    From testarea-pdfbox2 with Apache License 2.0 5 votes vote down vote up
@Override
public void process(Operator operator, List<COSBase> operands) throws IOException {
    PDGraphicsState gs = getGraphicsState();

    linePath.setWindingRule(GeneralPath.WIND_EVEN_ODD);
    addFillPath(gs.getNonStrokingColor());
    linePath.reset();
}
 
Example #11
Source File: PdfToTextInfoConverter.java    From testarea-pdfbox2 with Apache License 2.0 5 votes vote down vote up
@Override
public final void process(Operator operator, List<COSBase> operands) throws IOException {
    PDGraphicsState gs = getGraphicsState();    
    linePath.setWindingRule(GeneralPath.WIND_NON_ZERO);
    addFillPath(gs.getNonStrokingColor());
    linePath.reset();
}
 
Example #12
Source File: PdfToTextInfoConverter.java    From testarea-pdfbox2 with Apache License 2.0 5 votes vote down vote up
@Override
protected void processTextPosition(TextPosition text) {
    PDGraphicsState gs = getGraphicsState();
    // check opacity for stroke and fill text 
    if (gs.getAlphaConstant() < Constants.EPSILON && gs.getNonStrokeAlphaConstant() < Constants.EPSILON) {
        return;
    }                       

    Vector center = getTextPositionCenterPoint(text);
    Area area = gs.getCurrentClippingPath();
    if (area == null || area.contains(lowerLeftX + center.getX(), lowerLeftY + center.getY())) {            
        nonStrokingColors.put(text, gs.getNonStrokingColor());
        super.processTextPosition(text);
    }
}
 
Example #13
Source File: PdfToTextInfoConverter.java    From testarea-pdfbox2 with Apache License 2.0 5 votes vote down vote up
@Override
public void process(Operator operator, List<COSBase> operands) throws IOException {
    PDGraphicsState gs = getGraphicsState();
    linePath.setWindingRule(GeneralPath.WIND_EVEN_ODD);
    addFillPath(gs.getNonStrokingColor());
    linePath.reset();
}
 
Example #14
Source File: PathDrawer.java    From Pdf2Dom with GNU Lesser General Public License v3.0 4 votes vote down vote up
public PathDrawer(PDGraphicsState state)
{
    this.state = state;
}
 
Example #15
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
/**
 * @return Returns the graphicsState.
 */
public PDGraphicsState getGraphicsState()
{
    return graphicsStack.peek();
}
 
Example #16
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
/**
 * Process text from the PDF Stream. You should override this method if you want to
 * perform an action when encoded text is being processed.
 *
 * @param string the encoded text
 * @throws IOException if there is an error processing the string
 */
protected void showText(byte[] string) throws IOException
{
    PDGraphicsState state = getGraphicsState();
    PDTextState textState = state.getTextState();

    // get the current font
    PDFont font = textState.getFont();
    if (font == null)
    {
        LOG.warn("No current font, will use default");
        font = PDFontFactory.createDefaultFont();
    }

    float fontSize = textState.getFontSize();
    float horizontalScaling = textState.getHorizontalScaling() / 100f;
    float charSpacing = textState.getCharacterSpacing();

    // put the text state parameters into matrix form
    Matrix parameters = new Matrix(
            fontSize * horizontalScaling, 0, // 0
            0, fontSize,                     // 0
            0, textState.getRise());         // 1

    // read the stream until it is empty
    InputStream in = new ByteArrayInputStream(string);
    while (in.available() > 0)
    {
        // decode a character
        int before = in.available();
        int code = font.readCode(in);
        int codeLength = before - in.available();
        String unicode = font.toUnicode(code);

        // Word spacing shall be applied to every occurrence of the single-byte character code
        // 32 in a string when using a simple font or a composite font that defines code 32 as
        // a single-byte code.
        float wordSpacing = 0;
        if (codeLength == 1 && code == 32)
        {
            wordSpacing += textState.getWordSpacing();
        }

        // text rendering matrix (text space -> device space)
        Matrix ctm = state.getCurrentTransformationMatrix();
        Matrix textRenderingMatrix = parameters.multiply(textMatrix).multiply(ctm);

        // get glyph's position vector if this is vertical text
        // changes to vertical text should be tested with PDFBOX-2294 and PDFBOX-1422
        if (font.isVertical())
        {
            // position vector, in text space
            Vector v = font.getPositionVector(code);

            // apply the position vector to the horizontal origin to get the vertical origin
            textRenderingMatrix.translate(v);
        }

        // get glyph's horizontal and vertical displacements, in text space
        Vector w = font.getDisplacement(code);

        // process the decoded glyph
        saveGraphicsState();
        Matrix textMatrixOld = textMatrix;
        Matrix textLineMatrixOld = textLineMatrix;
        showGlyph(textRenderingMatrix, font, code, unicode, w);
        textMatrix = textMatrixOld;
        textLineMatrix = textLineMatrixOld;
        restoreGraphicsState();

        // calculate the combined displacements
        float tx;
        float ty;
        if (font.isVertical())
        {
            tx = 0;
            ty = w.getY() * fontSize + charSpacing + wordSpacing;
        }
        else
        {
            tx = (w.getX() * fontSize + charSpacing + wordSpacing) * horizontalScaling;
            ty = 0;
        }

        // update the text matrix
        textMatrix.concatenate(Matrix.getTranslateInstance(tx, ty));
    }
}
 
Example #17
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
/**
 * 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);
    Deque<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);
}
 
Example #18
Source File: PageDrawer.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
/**
 * Render the font using the Glyph2D interface.
 * 
 * @param glyph2D the Glyph2D implementation provided a GeneralPath for each glyph
 * @param font the font
 * @param code character code
 * @param displacement the glyph's displacement (advance)
 * @param at the transformation
 * @throws IOException if something went wrong
 */
private void drawGlyph2D(Glyph2D glyph2D, PDFont font, int code, Vector displacement,
                         AffineTransform at) throws IOException
{
    PDGraphicsState state = getGraphicsState();
    RenderingMode renderingMode = state.getTextState().getRenderingMode();

    GeneralPath path = glyph2D.getPathForCharacterCode(code);
    if (path != null)
    {
        // Stretch non-embedded glyph if it does not match the height/width contained in the PDF.
        // Vertical fonts have zero X displacement, so the following code scales to 0 if we don't skip it.
        // TODO: How should vertical fonts be handled?
        if (!font.isEmbedded() && !font.isVertical() && !font.isStandard14() && font.hasExplicitWidth(code))
        {
            float fontWidth = font.getWidthFromFont(code);
            if (fontWidth > 0 && // ignore spaces
                    Math.abs(fontWidth - displacement.getX() * 1000) > 0.0001)
            {
                float pdfWidth = displacement.getX() * 1000;
                at.scale(pdfWidth / fontWidth, 1);
            }
        }

        // render glyph
        Shape glyph = at.createTransformedShape(path);

        if (renderingMode.isFill())
        {
            graphics.setComposite(state.getNonStrokingJavaComposite());
            graphics.setPaint(getNonStrokingPaint());
            setClip();
            if (isContentRendered())
            {
                graphics.fill(glyph);
            }
        }

        if (renderingMode.isStroke())
        {
            graphics.setComposite(state.getStrokingJavaComposite());
            graphics.setPaint(getStrokingPaint());
            graphics.setStroke(getStroke());
            setClip();
            if (isContentRendered())
            {
                graphics.draw(glyph);
            }
        }

        if (renderingMode.isClip())
        {
            textClippings.add(glyph);
        }
    }
}
 
Example #19
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 2 votes vote down vote up
/**
 * Restores the entire graphics stack.
 * 
 * @param snapshot the graphics state stack to be restored.
 */
protected final void restoreGraphicsStack(Deque<PDGraphicsState> snapshot)
{
    graphicsStack = snapshot;
}