Search in sources :

Example 1 with COSName

use of com.tom_roush.pdfbox.cos.COSName in project PdfBox-Android by TomRoush.

the class Overlay method overlayPage.

private void overlayPage(PDPage page, LayoutPage layoutPage, COSArray array) throws IOException {
    PDResources resources = page.getResources();
    if (resources == null) {
        resources = new PDResources();
        page.setResources(resources);
    }
    COSName xObjectId = createOverlayXObject(page, layoutPage);
    array.add(createOverlayStream(page, layoutPage, xObjectId));
}
Also used : COSName(com.tom_roush.pdfbox.cos.COSName) PDResources(com.tom_roush.pdfbox.pdmodel.PDResources)

Example 2 with COSName

use of com.tom_roush.pdfbox.cos.COSName in project PdfBox-Android by TomRoush.

the class PDFCloneUtility method cloneMerge.

/**
 * Merges two objects of the same type by deep-cloning its members.
 * <br>
 * Base and target must be instances of the same class.
 * @param base the base object to be cloned
 * @param target the merge target
 * @throws IOException if an I/O error occurs
 */
public void cloneMerge(final COSObjectable base, COSObjectable target) throws IOException {
    if (base == null) {
        return;
    }
    COSBase retval = clonedVersion.get(base);
    if (retval != null) {
        return;
    // we are done, it has already been converted. // ### Is that correct for cloneMerge???
    }
    // TODO what when clone-merging a clone? Does it ever happen?
    if (!(base instanceof COSBase)) {
        cloneMerge(base.getCOSObject(), target.getCOSObject());
    } else if (base instanceof COSObject) {
        if (target instanceof COSObject) {
            cloneMerge(((COSObject) base).getObject(), ((COSObject) target).getObject());
        } else if (target instanceof COSDictionary || target instanceof COSArray) {
            cloneMerge(((COSObject) base).getObject(), target);
        }
    } else if (base instanceof COSArray) {
        COSArray array = (COSArray) base;
        for (int i = 0; i < array.size(); i++) {
            ((COSArray) target).add(cloneForNewDocument(array.get(i)));
        }
    } else if (base instanceof COSStream) {
        // does that make sense???
        COSStream originalStream = (COSStream) base;
        COSStream stream = destination.getDocument().createCOSStream();
        OutputStream output = stream.createOutputStream(originalStream.getFilters());
        IOUtils.copy(originalStream.createInputStream(), output);
        output.close();
        clonedVersion.put(base, stream);
        for (Map.Entry<COSName, COSBase> entry : originalStream.entrySet()) {
            stream.setItem(entry.getKey(), cloneForNewDocument(entry.getValue()));
        }
        retval = stream;
    } else if (base instanceof COSDictionary) {
        COSDictionary dic = (COSDictionary) base;
        clonedVersion.put(base, retval);
        for (Map.Entry<COSName, COSBase> entry : dic.entrySet()) {
            COSName key = entry.getKey();
            COSBase value = entry.getValue();
            if (((COSDictionary) target).getItem(key) != null) {
                cloneMerge(value, ((COSDictionary) target).getItem(key));
            } else {
                ((COSDictionary) target).setItem(key, cloneForNewDocument(value));
            }
        }
    } else {
        retval = (COSBase) base;
    }
    clonedVersion.put(base, retval);
    clonedValues.add(retval);
}
Also used : COSStream(com.tom_roush.pdfbox.cos.COSStream) COSDictionary(com.tom_roush.pdfbox.cos.COSDictionary) COSArray(com.tom_roush.pdfbox.cos.COSArray) COSName(com.tom_roush.pdfbox.cos.COSName) COSObject(com.tom_roush.pdfbox.cos.COSObject) OutputStream(java.io.OutputStream) COSBase(com.tom_roush.pdfbox.cos.COSBase) HashMap(java.util.HashMap) Map(java.util.Map)

Example 3 with COSName

use of com.tom_roush.pdfbox.cos.COSName 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 4 with COSName

use of com.tom_roush.pdfbox.cos.COSName 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 5 with COSName

use of com.tom_roush.pdfbox.cos.COSName in project PdfBox-Android by TomRoush.

the class PDSquigglyAppearanceHandler method generateNormalAppearance.

@Override
public void generateNormalAppearance() {
    PDAnnotationTextMarkup annotation = (PDAnnotationTextMarkup) getAnnotation();
    PDRectangle rect = annotation.getRectangle();
    float[] pathsArray = annotation.getQuadPoints();
    if (pathsArray == null) {
        return;
    }
    AnnotationBorder ab = AnnotationBorder.getAnnotationBorder(annotation, annotation.getBorderStyle());
    PDColor color = annotation.getColor();
    if (color == null || color.getComponents().length == 0) {
        return;
    }
    if (Float.compare(ab.width, 0) == 0) {
        // value found in adobe reader
        ab.width = 1.5f;
    }
    // Adjust rectangle even if not empty, see PLPDF.com-MarkupAnnotations.pdf
    // TODO in a class structure this should be overridable
    // this is similar to polyline but different data type
    // all coordinates (unlike painting) are used because I'm lazy
    float minX = Float.MAX_VALUE;
    float minY = Float.MAX_VALUE;
    float maxX = Float.MIN_VALUE;
    float maxY = Float.MIN_VALUE;
    for (int i = 0; i < pathsArray.length / 2; ++i) {
        float x = pathsArray[i * 2];
        float y = pathsArray[i * 2 + 1];
        minX = Math.min(minX, x);
        minY = Math.min(minY, y);
        maxX = Math.max(maxX, x);
        maxY = Math.max(maxY, y);
    }
    rect.setLowerLeftX(Math.min(minX - ab.width / 2, rect.getLowerLeftX()));
    rect.setLowerLeftY(Math.min(minY - ab.width / 2, rect.getLowerLeftY()));
    rect.setUpperRightX(Math.max(maxX + ab.width / 2, rect.getUpperRightX()));
    rect.setUpperRightY(Math.max(maxY + ab.width / 2, rect.getUpperRightY()));
    annotation.setRectangle(rect);
    PDAppearanceContentStream cs = null;
    try {
        cs = getNormalAppearanceAsContentStream();
        setOpacity(cs, annotation.getConstantOpacity());
        cs.setStrokingColor(color);
        // https://stackoverflow.com/questions/9855814/pdf-spec-vs-acrobat-creation-quadpoints
        for (int i = 0; i < pathsArray.length / 8; ++i) {
            // Adobe uses a fixed pattern that assumes a height of 40, and it transforms to that height
            // horizontally and the same / 1.8 vertically.
            // translation apparently based on bottom left, but slightly different in Adobe
            // TODO what if the annotation is not horizontal?
            float height = pathsArray[i * 8 + 1] - pathsArray[i * 8 + 5];
            cs.transform(new Matrix(height / 40f, 0, 0, height / 40f / 1.8f, pathsArray[i * 8 + 4], pathsArray[i * 8 + 5]));
            // Create form, BBox is mostly fixed, except for the horizontal size which is
            // horizontal size divided by the horizontal transform factor from above
            // (almost)
            PDFormXObject form = new PDFormXObject(createCOSStream());
            form.setBBox(new PDRectangle(-0.5f, -0.5f, (pathsArray[i * 8 + 2] - pathsArray[i * 8]) / height * 40f + 0.5f, 13));
            form.setResources(new PDResources());
            form.setMatrix(AffineTransform.getTranslateInstance(0.5f, 0.5f));
            cs.drawForm(form);
            PDFormContentStream formCS = null;
            try {
                formCS = new PDFormContentStream(form);
                PDTilingPattern pattern = new PDTilingPattern();
                pattern.setBBox(new PDRectangle(0, 0, 10, 12));
                pattern.setXStep(10);
                pattern.setYStep(13);
                pattern.setTilingType(PDTilingPattern.TILING_CONSTANT_SPACING_FASTER_TILING);
                pattern.setPaintType(PDTilingPattern.PAINT_UNCOLORED);
                PDPatternContentStream patternCS = null;
                try {
                    patternCS = new PDPatternContentStream(pattern);
                    // from Adobe
                    patternCS.setLineCapStyle(1);
                    patternCS.setLineJoinStyle(1);
                    patternCS.setLineWidth(1);
                    patternCS.setMiterLimit(10);
                    patternCS.moveTo(0, 1);
                    patternCS.lineTo(5, 11);
                    patternCS.lineTo(10, 1);
                    patternCS.stroke();
                } finally {
                    IOUtils.closeQuietly(patternCS);
                }
                COSName patternName = form.getResources().add(pattern);
                // PDColorSpace patternColorSpace = new PDPattern(null, PDDeviceRGB.INSTANCE);
                // PDColor patternColor = new PDColor(color.getComponents(), patternName, patternColorSpace);
                // formCS.setNonStrokingColor(patternColor); TODO: PdfBox-Android
                // With Adobe, the horizontal size is slightly different, don't know why
                formCS.addRect(0, 0, (pathsArray[i * 8 + 2] - pathsArray[i * 8]) / height * 40f, 12);
                formCS.fill();
            } finally {
                IOUtils.closeQuietly(formCS);
            }
        }
    } catch (IOException ex) {
        Log.e("PdfBox-Android", ex.getMessage(), ex);
    } finally {
        IOUtils.closeQuietly(cs);
    }
}
Also used : PDFormContentStream(com.tom_roush.pdfbox.pdmodel.PDFormContentStream) PDAnnotationTextMarkup(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup) PDPatternContentStream(com.tom_roush.pdfbox.pdmodel.PDPatternContentStream) PDResources(com.tom_roush.pdfbox.pdmodel.PDResources) IOException(java.io.IOException) PDColor(com.tom_roush.pdfbox.pdmodel.graphics.color.PDColor) Matrix(com.tom_roush.pdfbox.util.Matrix) PDTilingPattern(com.tom_roush.pdfbox.pdmodel.graphics.pattern.PDTilingPattern) COSName(com.tom_roush.pdfbox.cos.COSName) PDAppearanceContentStream(com.tom_roush.pdfbox.pdmodel.PDAppearanceContentStream) PDFormXObject(com.tom_roush.pdfbox.pdmodel.graphics.form.PDFormXObject) PDRectangle(com.tom_roush.pdfbox.pdmodel.common.PDRectangle)

Aggregations

COSName (com.tom_roush.pdfbox.cos.COSName)83 COSBase (com.tom_roush.pdfbox.cos.COSBase)50 COSArray (com.tom_roush.pdfbox.cos.COSArray)27 IOException (java.io.IOException)24 COSDictionary (com.tom_roush.pdfbox.cos.COSDictionary)23 COSObject (com.tom_roush.pdfbox.cos.COSObject)11 COSString (com.tom_roush.pdfbox.cos.COSString)11 HashMap (java.util.HashMap)10 Map (java.util.Map)10 PDResources (com.tom_roush.pdfbox.pdmodel.PDResources)9 COSStream (com.tom_roush.pdfbox.cos.COSStream)7 PDFormXObject (com.tom_roush.pdfbox.pdmodel.graphics.form.PDFormXObject)7 MissingOperandException (com.tom_roush.pdfbox.contentstream.operator.MissingOperandException)5 COSInteger (com.tom_roush.pdfbox.cos.COSInteger)5 COSNumber (com.tom_roush.pdfbox.cos.COSNumber)5 PDXObject (com.tom_roush.pdfbox.pdmodel.graphics.PDXObject)5 PDRectangle (com.tom_roush.pdfbox.pdmodel.common.PDRectangle)4 PDTransparencyGroup (com.tom_roush.pdfbox.pdmodel.graphics.form.PDTransparencyGroup)4 OutputStream (java.io.OutputStream)4 Operator (com.tom_roush.pdfbox.contentstream.operator.Operator)3