Search in sources :

Example 1 with Operator

use of com.tom_roush.pdfbox.contentstream.operator.Operator in project PdfBox-Android by TomRoush.

the class ContentStreamWriter method writeObject.

private void writeObject(Object o) throws IOException {
    if (o instanceof COSString) {
        COSWriter.writeString((COSString) o, output);
        output.write(SPACE);
    } else if (o instanceof COSFloat) {
        ((COSFloat) o).writePDF(output);
        output.write(SPACE);
    } else if (o instanceof COSInteger) {
        ((COSInteger) o).writePDF(output);
        output.write(SPACE);
    } else if (o instanceof COSBoolean) {
        ((COSBoolean) o).writePDF(output);
        output.write(SPACE);
    } else if (o instanceof COSName) {
        ((COSName) o).writePDF(output);
        output.write(SPACE);
    } else if (o instanceof COSArray) {
        COSArray array = (COSArray) o;
        output.write(COSWriter.ARRAY_OPEN);
        for (int i = 0; i < array.size(); i++) {
            writeObject(array.get(i));
            output.write(SPACE);
        }
        output.write(COSWriter.ARRAY_CLOSE);
    } else if (o instanceof COSDictionary) {
        COSDictionary obj = (COSDictionary) o;
        output.write(COSWriter.DICT_OPEN);
        for (Map.Entry<COSName, COSBase> entry : obj.entrySet()) {
            if (entry.getValue() != null) {
                writeObject(entry.getKey());
                output.write(SPACE);
                writeObject(entry.getValue());
                output.write(SPACE);
            }
        }
        output.write(COSWriter.DICT_CLOSE);
        output.write(SPACE);
    } else if (o instanceof Operator) {
        Operator op = (Operator) o;
        if (op.getName().equals(OperatorName.BEGIN_INLINE_IMAGE)) {
            output.write(OperatorName.BEGIN_INLINE_IMAGE.getBytes(Charsets.ISO_8859_1));
            COSDictionary dic = op.getImageParameters();
            for (COSName key : dic.keySet()) {
                Object value = dic.getDictionaryObject(key);
                key.writePDF(output);
                output.write(SPACE);
                writeObject(value);
                output.write(EOL);
            }
            output.write(OperatorName.BEGIN_INLINE_IMAGE_DATA.getBytes(Charsets.ISO_8859_1));
            output.write(EOL);
            output.write(op.getImageData());
            output.write(EOL);
            output.write(OperatorName.END_INLINE_IMAGE.getBytes(Charsets.ISO_8859_1));
            output.write(EOL);
        } else {
            output.write(op.getName().getBytes(Charsets.ISO_8859_1));
            output.write(EOL);
        }
    } else {
        throw new IOException("Error:Unknown type in content stream:" + o);
    }
}
Also used : Operator(com.tom_roush.pdfbox.contentstream.operator.Operator) COSDictionary(com.tom_roush.pdfbox.cos.COSDictionary) IOException(java.io.IOException) COSBoolean(com.tom_roush.pdfbox.cos.COSBoolean) COSInteger(com.tom_roush.pdfbox.cos.COSInteger) COSName(com.tom_roush.pdfbox.cos.COSName) COSArray(com.tom_roush.pdfbox.cos.COSArray) COSBase(com.tom_roush.pdfbox.cos.COSBase) COSString(com.tom_roush.pdfbox.cos.COSString) Map(java.util.Map) COSFloat(com.tom_roush.pdfbox.cos.COSFloat)

Example 2 with Operator

use of com.tom_roush.pdfbox.contentstream.operator.Operator in project PdfBox-Android by TomRoush.

the class PDFStreamParser method parseNextToken.

/**
 * This will parse the next token in the stream.
 *
 * @return The next token in the stream or null if there are no more tokens in the stream.
 *
 * @throws IOException If an io error occurs while parsing the stream.
 */
public Object parseNextToken() throws IOException {
    Object retval;
    skipSpaces();
    int nextByte = seqSource.peek();
    if (((byte) nextByte) == -1) {
        return null;
    }
    char c = (char) nextByte;
    switch(c) {
        case '<':
            {
                // pull off first left bracket
                int leftBracket = seqSource.read();
                // check for second left bracket
                c = (char) seqSource.peek();
                // put back first bracket
                seqSource.unread(leftBracket);
                if (c == '<') {
                    retval = parseCOSDictionary();
                } else {
                    retval = parseCOSString();
                }
                break;
            }
        case '[':
            {
                // array
                retval = parseCOSArray();
                break;
            }
        case '(':
            // string
            retval = parseCOSString();
            break;
        case '/':
            // name
            retval = parseCOSName();
            break;
        case 'n':
            {
                // null
                String nullString = readString();
                if (nullString.equals("null")) {
                    retval = COSNull.NULL;
                } else {
                    retval = Operator.getOperator(nullString);
                }
                break;
            }
        case 't':
        case 'f':
            {
                String next = readString();
                if (next.equals("true")) {
                    retval = COSBoolean.TRUE;
                    break;
                } else if (next.equals("false")) {
                    retval = COSBoolean.FALSE;
                } else {
                    retval = Operator.getOperator(next);
                }
                break;
            }
        case 'R':
            {
                String line = readString();
                if (line.equals("R")) {
                    retval = new COSObject(null);
                } else {
                    retval = Operator.getOperator(line);
                }
                break;
            }
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case '-':
        case '+':
        case '.':
            {
                /* We will be filling buf with the rest of the number.  Only
                 * allow 1 "." and "-" and "+" at start of number. */
                StringBuilder buf = new StringBuilder();
                buf.append(c);
                seqSource.read();
                // Ignore double negative (this is consistent with Adobe Reader)
                if (c == '-' && seqSource.peek() == c) {
                    seqSource.read();
                }
                boolean dotNotRead = c != '.';
                while (Character.isDigit(c = (char) seqSource.peek()) || dotNotRead && c == '.' || c == '-') {
                    if (c != '-') {
                        // PDFBOX-4064: ignore "-" in the middle of a number
                        buf.append(c);
                    }
                    seqSource.read();
                    if (dotNotRead && c == '.') {
                        dotNotRead = false;
                    }
                }
                retval = COSNumber.get(buf.toString());
                break;
            }
        case 'B':
            {
                String next = readString();
                retval = Operator.getOperator(next);
                if (next.equals(OperatorName.BEGIN_INLINE_IMAGE)) {
                    Operator beginImageOP = (Operator) retval;
                    COSDictionary imageParams = new COSDictionary();
                    beginImageOP.setImageParameters(imageParams);
                    Object nextToken = null;
                    while ((nextToken = parseNextToken()) instanceof COSName) {
                        Object value = parseNextToken();
                        imageParams.setItem((COSName) nextToken, (COSBase) value);
                    }
                    // final token will be the image data, maybe??
                    if (nextToken instanceof Operator) {
                        Operator imageData = (Operator) nextToken;
                        if (imageData.getImageData() == null || imageData.getImageData().length == 0) {
                            Log.w("PdfBox-Android", "empty inline image at stream offset " + seqSource.getPosition());
                        }
                        beginImageOP.setImageData(imageData.getImageData());
                    }
                }
                break;
            }
        case 'I':
            {
                // Special case for ID operator
                String id = Character.toString((char) seqSource.read()) + (char) seqSource.read();
                if (!id.equals(OperatorName.BEGIN_INLINE_IMAGE_DATA)) {
                    throw new IOException("Error: Expected operator 'ID' actual='" + id + "' at stream offset " + seqSource.getPosition());
                }
                ByteArrayOutputStream imageData = new ByteArrayOutputStream();
                if (isWhitespace()) {
                    // pull off the whitespace character
                    seqSource.read();
                }
                int lastByte = seqSource.read();
                int currentByte = seqSource.read();
                // Be aware not all kind of whitespaces are allowed here. see PDFBOX-1561
                while (!(lastByte == 'E' && currentByte == 'I' && hasNextSpaceOrReturn() && hasNoFollowingBinData(seqSource)) && !seqSource.isEOF()) {
                    imageData.write(lastByte);
                    lastByte = currentByte;
                    currentByte = seqSource.read();
                }
                // the EI operator isn't unread, as it won't be processed anyway
                retval = Operator.getOperator(OperatorName.BEGIN_INLINE_IMAGE_DATA);
                // save the image data to the operator, so that it can be accessed later
                ((Operator) retval).setImageData(imageData.toByteArray());
                break;
            }
        case ']':
            {
                // some ']' around without its previous '['
                // this means a PDF is somewhat corrupt but we will continue to parse.
                seqSource.read();
                // must be a better solution than null...
                retval = COSNull.NULL;
                break;
            }
        default:
            {
                // we must be an operator
                String operator = readOperator();
                if (operator.trim().length() == 0) {
                    // we have a corrupt stream, stop reading here
                    retval = null;
                } else {
                    retval = Operator.getOperator(operator);
                }
            }
    }
    return retval;
}
Also used : Operator(com.tom_roush.pdfbox.contentstream.operator.Operator) COSDictionary(com.tom_roush.pdfbox.cos.COSDictionary) COSName(com.tom_roush.pdfbox.cos.COSName) COSObject(com.tom_roush.pdfbox.cos.COSObject) COSBase(com.tom_roush.pdfbox.cos.COSBase) COSObject(com.tom_roush.pdfbox.cos.COSObject) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream)

Example 3 with Operator

use of com.tom_roush.pdfbox.contentstream.operator.Operator in project PdfBox-Android by TomRoush.

the class PDFreeTextAppearanceHandler method extractNonStrokingColor.

// get the last non stroking color from the /DA entry
private PDColor extractNonStrokingColor(PDAnnotationMarkup annotation) {
    // It could also work with a regular expression, but that should be written so that
    // "/LucidaConsole 13.94766 Tf .392 .585 .93 rg" does not produce "2 .585 .93 rg" as result
    // Another alternative might be to create a PDDocument and a PDPage with /DA content as /Content,
    // process the whole thing and then get the non stroking color.
    PDColor strokingColor = new PDColor(new float[] { 0 }, PDDeviceGray.INSTANCE);
    String defaultAppearance = annotation.getDefaultAppearance();
    if (defaultAppearance == null) {
        return strokingColor;
    }
    try {
        // not sure if charset is correct, but we only need numbers and simple characters
        PDFStreamParser parser = new PDFStreamParser(defaultAppearance.getBytes(Charsets.US_ASCII));
        COSArray arguments = new COSArray();
        COSArray colors = null;
        Operator graphicOp = null;
        for (Object token = parser.parseNextToken(); token != null; token = parser.parseNextToken()) {
            if (token instanceof COSObject) {
                arguments.add(((COSObject) token).getObject());
            } else if (token instanceof Operator) {
                Operator op = (Operator) token;
                String name = op.getName();
                if (OperatorName.NON_STROKING_GRAY.equals(name) || OperatorName.NON_STROKING_RGB.equals(name) || OperatorName.NON_STROKING_CMYK.equals(name)) {
                    graphicOp = op;
                    colors = arguments;
                }
                arguments = new COSArray();
            } else {
                arguments.add((COSBase) token);
            }
        }
        if (graphicOp != null) {
            String graphicOpName = graphicOp.getName();
            if (OperatorName.NON_STROKING_GRAY.equals(graphicOpName)) {
                strokingColor = new PDColor(colors, PDDeviceGray.INSTANCE);
            } else if (OperatorName.NON_STROKING_RGB.equals(graphicOpName)) {
                strokingColor = new PDColor(colors, PDDeviceRGB.INSTANCE);
            } else if (OperatorName.NON_STROKING_CMYK.equals(graphicOpName)) {
            // strokingColor = new PDColor(colors, PDDeviceCMYK.INSTANCE); TODO: PdfBox-Android
            }
        }
    } catch (IOException ex) {
        Log.w("PdfBox-Android", "Problem parsing /DA, will use default black", ex);
    }
    return strokingColor;
}
Also used : Operator(com.tom_roush.pdfbox.contentstream.operator.Operator) PDFStreamParser(com.tom_roush.pdfbox.pdfparser.PDFStreamParser) COSArray(com.tom_roush.pdfbox.cos.COSArray) COSObject(com.tom_roush.pdfbox.cos.COSObject) COSBase(com.tom_roush.pdfbox.cos.COSBase) COSObject(com.tom_roush.pdfbox.cos.COSObject) IOException(java.io.IOException) PDColor(com.tom_roush.pdfbox.pdmodel.graphics.color.PDColor)

Example 4 with Operator

use of com.tom_roush.pdfbox.contentstream.operator.Operator in project PdfBox-Android by TomRoush.

the class PDType3CharProc method getWidth.

/**
 * Get the width from a type3 charproc stream.
 *
 * @return the glyph width.
 * @throws IOException if the stream could not be read, or did not have d0 or d1 as first
 * operator, or if their first argument was not a number.
 */
public float getWidth() throws IOException {
    List<COSBase> arguments = new ArrayList<COSBase>();
    PDFStreamParser parser = new PDFStreamParser(this);
    Object token = parser.parseNextToken();
    while (token != null) {
        if (token instanceof COSObject) {
            arguments.add(((COSObject) token).getObject());
        } else if (token instanceof Operator) {
            return parseWidth((Operator) token, arguments);
        } else {
            arguments.add((COSBase) token);
        }
        token = parser.parseNextToken();
    }
    throw new IOException("Unexpected end of stream");
}
Also used : Operator(com.tom_roush.pdfbox.contentstream.operator.Operator) PDFStreamParser(com.tom_roush.pdfbox.pdfparser.PDFStreamParser) COSObject(com.tom_roush.pdfbox.cos.COSObject) ArrayList(java.util.ArrayList) COSBase(com.tom_roush.pdfbox.cos.COSBase) COSObject(com.tom_roush.pdfbox.cos.COSObject) IOException(java.io.IOException)

Example 5 with Operator

use of com.tom_roush.pdfbox.contentstream.operator.Operator in project PdfBox-Android by TomRoush.

the class PDType3CharProc method getGlyphBBox.

/**
 * Calculate the bounding box of this glyph. This will work only if the first operator in the
 * stream is d1.
 *
 * @return the bounding box of this glyph, or null if the first operator is not d1.
 * @throws IOException If an io error occurs while parsing the stream.
 */
public PDRectangle getGlyphBBox() throws IOException {
    List<COSBase> arguments = new ArrayList<COSBase>();
    PDFStreamParser parser = new PDFStreamParser(this);
    Object token = parser.parseNextToken();
    while (token != null) {
        if (token instanceof COSObject) {
            arguments.add(((COSObject) token).getObject());
        } else if (token instanceof Operator) {
            if (((Operator) token).getName().equals("d1") && arguments.size() == 6) {
                for (int i = 0; i < 6; ++i) {
                    if (!(arguments.get(i) instanceof COSNumber)) {
                        return null;
                    }
                }
                return new PDRectangle(((COSNumber) arguments.get(2)).floatValue(), ((COSNumber) arguments.get(3)).floatValue(), ((COSNumber) arguments.get(4)).floatValue() - ((COSNumber) arguments.get(2)).floatValue(), ((COSNumber) arguments.get(5)).floatValue() - ((COSNumber) arguments.get(3)).floatValue());
            } else {
                return null;
            }
        } else {
            arguments.add((COSBase) token);
        }
        token = parser.parseNextToken();
    }
    return null;
}
Also used : Operator(com.tom_roush.pdfbox.contentstream.operator.Operator) PDFStreamParser(com.tom_roush.pdfbox.pdfparser.PDFStreamParser) COSObject(com.tom_roush.pdfbox.cos.COSObject) ArrayList(java.util.ArrayList) COSNumber(com.tom_roush.pdfbox.cos.COSNumber) COSBase(com.tom_roush.pdfbox.cos.COSBase) COSObject(com.tom_roush.pdfbox.cos.COSObject) PDRectangle(com.tom_roush.pdfbox.pdmodel.common.PDRectangle)

Aggregations

Operator (com.tom_roush.pdfbox.contentstream.operator.Operator)9 COSBase (com.tom_roush.pdfbox.cos.COSBase)8 COSObject (com.tom_roush.pdfbox.cos.COSObject)7 PDFStreamParser (com.tom_roush.pdfbox.pdfparser.PDFStreamParser)6 IOException (java.io.IOException)5 ArrayList (java.util.ArrayList)4 COSArray (com.tom_roush.pdfbox.cos.COSArray)3 COSName (com.tom_roush.pdfbox.cos.COSName)3 COSDictionary (com.tom_roush.pdfbox.cos.COSDictionary)2 COSNumber (com.tom_roush.pdfbox.cos.COSNumber)2 COSBoolean (com.tom_roush.pdfbox.cos.COSBoolean)1 COSFloat (com.tom_roush.pdfbox.cos.COSFloat)1 COSInteger (com.tom_roush.pdfbox.cos.COSInteger)1 COSString (com.tom_roush.pdfbox.cos.COSString)1 PDRectangle (com.tom_roush.pdfbox.pdmodel.common.PDRectangle)1 PDColor (com.tom_roush.pdfbox.pdmodel.graphics.color.PDColor)1 PDFormXObject (com.tom_roush.pdfbox.pdmodel.graphics.form.PDFormXObject)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 Map (java.util.Map)1