Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,25 @@
*/
package org.openpdf.text.pdf.parser;

import org.openpdf.text.ExceptionConverter;
import org.openpdf.text.error_messages.MessageLocalization;
import org.openpdf.text.pdf.CMapAwareDocumentFont;
import org.openpdf.text.pdf.PdfArray;
import org.openpdf.text.pdf.PdfContentParser;
import org.openpdf.text.pdf.PdfDictionary;
import org.openpdf.text.pdf.PdfIndirectReference;
import org.openpdf.text.pdf.PdfLiteral;
import org.openpdf.text.pdf.PdfName;
import org.openpdf.text.pdf.PdfNumber;
import org.openpdf.text.pdf.PdfObject;
import org.openpdf.text.pdf.PdfReader;
import org.openpdf.text.pdf.PdfStream;
import org.openpdf.text.pdf.PdfString;
import org.openpdf.text.pdf.PdfName;
import org.openpdf.text.pdf.PdfArray;
import org.openpdf.text.pdf.PdfIndirectReference;
import org.openpdf.text.pdf.PRIndirectReference;
import org.openpdf.text.pdf.PRStream;
import org.openpdf.text.pdf.PRTokeniser;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -891,4 +899,104 @@
handler.popContext();
}
}

/**
* Processes PDF content stream bytes.
*
* @param contentBytes the bytes of a content stream
* @param resources the resources that come with the content stream
*/
protected void processContent(byte[] contentBytes, PdfDictionary resources) {
try {
PdfContentParser pdfContentParser = new PdfContentParser(new PRTokeniser(contentBytes));
List<PdfObject> operands = new ArrayList<>();
while (!pdfContentParser.parse(operands).isEmpty()) {
PdfLiteral operator = (PdfLiteral) operands.getLast();
invokeOperator(operator, operands, resources);
}
} catch (Exception e) {
throw new ExceptionConverter(e);
}
}

/**
* Gets the content bytes from a PdfObject, which may be a reference, a stream or an array.
* This is a utility method that can be used by subclasses and other classes in this package.
*
* @param object the object to read bytes from
* @return the content bytes
* @throws java.io.IOException if there's an error reading the content
*/
protected byte[] getContentBytesFromPdfObject(PdfObject object) throws java.io.IOException {

Check notice on line 930 in openpdf-core/src/main/java/org/openpdf/text/pdf/parser/PdfContentStreamHandler.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

openpdf-core/src/main/java/org/openpdf/text/pdf/parser/PdfContentStreamHandler.java#L930

Unnecessary use of fully qualified name 'java.io.IOException' due to existing import 'java.io.IOException'
return getContentBytesFromPdfObjectStatic(object);
}

/**
* Gets the content bytes from a PdfObject, which may be a reference, a stream or an array.
* This is a static utility method that can be used by any class in this package.
*
* @param object the object to read bytes from
* @return the content bytes
* @throws IOException if there's an error reading the content
*/
static byte[] getContentBytesFromPdfObjectStatic(PdfObject object) throws IOException {
switch (object.type()) {
case PdfObject.INDIRECT:
return getContentBytesFromPdfObjectStatic(PdfReader.getPdfObject(object));
case PdfObject.STREAM:
return PdfReader.getStreamBytes((PRStream) PdfReader.getPdfObject(object));
case PdfObject.ARRAY:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (PdfObject element : ((PdfArray) object).getElements()) {
baos.write(getContentBytesFromPdfObjectStatic(element));
}
return baos.toByteArray();
default:
throw new IllegalStateException("Unsupported type: " + object.getClass().getCanonicalName());
}
}

/**
* A content operator implementation (Do) for handling XObject forms.
*/
protected class Do implements ContentOperator {

/**
* @see ContentOperator#getOperatorName()
*/
@Override
public String getOperatorName() {
return "Do";
}

@Override
public void invoke(List<PdfObject> operands, PdfContentStreamHandler handler, PdfDictionary resources) {
PdfObject firstOperand = operands.getFirst();
if (firstOperand instanceof PdfName) {
PdfName name = (PdfName) firstOperand;
PdfDictionary dictionary = resources.getAsDict(PdfName.XOBJECT);
if (dictionary == null) {
return;
}
PdfStream stream = (PdfStream) dictionary.getDirectObject(name);
PdfName subType = stream.getAsName(PdfName.SUBTYPE);
if (PdfName.FORM.equals(subType)) {
PdfDictionary resources2 = stream.getAsDict(PdfName.RESOURCES);
if (resources2 == null) {
resources2 = resources;
}

byte[] data;
try {
data = handler.getContentBytesFromPdfObject(stream);
} catch (IOException ex) {
throw new ExceptionConverter(ex);
}
new PushGraphicsState().invoke(operands, handler, resources);
handler.processContent(data, resources2);
new PopGraphicsState().invoke(operands, handler, resources);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public PdfContentTextExtractor(TextAssembler renderListener) {
@Override
protected void installDefaultOperators() {
super.installDefaultOperators();
registerContentOperator(new Do());
registerContentOperator(this.new Do());
}

void popContext() {
Expand Down Expand Up @@ -149,77 +149,4 @@ public String getResultantText() {
}
return res.toString().trim();
}

private class Do implements ContentOperator {

/**
* @see ContentOperator#getOperatorName()
*/
@Override
public String getOperatorName() {
return "Do";
}

@Override
public void invoke(List<PdfObject> operands, PdfContentStreamHandler handler, PdfDictionary resources) {
PdfObject firstOperand = operands.get(0);
if (firstOperand instanceof PdfName) {
PdfName name = (PdfName) firstOperand;
PdfDictionary dictionary = resources.getAsDict(PdfName.XOBJECT);
if (dictionary == null) {
return;
}
PdfStream stream = (PdfStream) dictionary.getDirectObject(name);
PdfName subType = stream.getAsName(PdfName.SUBTYPE);
if (PdfName.FORM.equals(subType)) {
PdfDictionary resources2 = stream.getAsDict(PdfName.RESOURCES);
if (resources2 == null) {
resources2 = resources;
}

byte[] data;
try {
data = getContentBytesFromPdfObject(stream);
} catch (IOException ex) {
throw new ExceptionConverter(ex);
}
new PushGraphicsState().invoke(operands, handler, resources);
processContent(data, resources2);
new PopGraphicsState().invoke(operands, handler, resources);
}
}

}

private void processContent(byte[] contentBytes, PdfDictionary resources) {
try {
PdfContentParser pdfContentParser = new PdfContentParser(new PRTokeniser(contentBytes));
List<PdfObject> operands = new ArrayList<>();
while (!pdfContentParser.parse(operands).isEmpty()) {
PdfLiteral operator = (PdfLiteral) operands.get(operands.size() - 1);
invokeOperator(operator, operands, resources);
}
} catch (Exception e) {
throw new ExceptionConverter(e);
}
}


private byte[] getContentBytesFromPdfObject(PdfObject object) throws IOException {
switch (object.type()) {
case PdfObject.INDIRECT:
return getContentBytesFromPdfObject(PdfReader.getPdfObject(object));
case PdfObject.STREAM:
return PdfReader.getStreamBytes((PRStream) PdfReader.getPdfObject(object));
case PdfObject.ARRAY:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (PdfObject element : ((PdfArray) object).getElements()) {
baos.write(getContentBytesFromPdfObject(element));
}
return baos.toByteArray();
default:
throw new IllegalStateException("Unsupported type: " + object.getClass().getCanonicalName());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public PdfContentTextLocator(TextAssembler renderListener, String pattern, int p
@Override
protected void installDefaultOperators() {
super.installDefaultOperators();
registerContentOperator(new Do());
registerContentOperator(this.new Do());
}

void popContext() {
Expand Down Expand Up @@ -167,77 +167,4 @@ public String getResultantText() {
public ArrayList<MatchedPattern> getMatchedPatterns() {
return this.accumulator;
}

private class Do implements ContentOperator {

/**
* @see ContentOperator#getOperatorName()
*/
@Override
public String getOperatorName() {
return "Do";
}

@Override
public void invoke(List<PdfObject> operands, PdfContentStreamHandler handler, PdfDictionary resources) {
PdfObject firstOperand = operands.getFirst();
if (firstOperand instanceof PdfName) {
PdfName name = (PdfName) firstOperand;
PdfDictionary dictionary = resources.getAsDict(PdfName.XOBJECT);
if (dictionary == null) {
return;
}
PdfStream stream = (PdfStream) dictionary.getDirectObject(name);
PdfName subType = stream.getAsName(PdfName.SUBTYPE);
if (PdfName.FORM.equals(subType)) {
PdfDictionary resources2 = stream.getAsDict(PdfName.RESOURCES);
if (resources2 == null) {
resources2 = resources;
}

byte[] data;
try {
data = getContentBytesFromPdfObject(stream);
} catch (IOException ex) {
throw new ExceptionConverter(ex);
}
new PushGraphicsState().invoke(operands, handler, resources);
processContent(data, resources2);
new PopGraphicsState().invoke(operands, handler, resources);
}
}

}

private void processContent(byte[] contentBytes, PdfDictionary resources) {
try {
PdfContentParser pdfContentParser = new PdfContentParser(new PRTokeniser(contentBytes));
List<PdfObject> operands = new ArrayList<>();
while (!pdfContentParser.parse(operands).isEmpty()) {
PdfLiteral operator = (PdfLiteral) operands.getLast();
invokeOperator(operator, operands, resources);
}
} catch (Exception e) {
throw new ExceptionConverter(e);
}
}


private byte[] getContentBytesFromPdfObject(PdfObject object) throws IOException {
switch (object.type()) {
case PdfObject.INDIRECT:
return getContentBytesFromPdfObject(PdfReader.getPdfObject(object));
case PdfObject.STREAM:
return PdfReader.getStreamBytes((PRStream) PdfReader.getPdfObject(object));
case PdfObject.ARRAY:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (PdfObject element : ((PdfArray) object).getElements()) {
baos.write(getContentBytesFromPdfObject(element));
}
return baos.toByteArray();
default:
throw new IllegalStateException("Unsupported type: " + object.getClass().getCanonicalName());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,32 +138,7 @@ private byte[] getContentBytesForPage(int pageNum) throws IOException {
* @throws IOException
*/
private byte[] getContentBytesFromContentObject(PdfObject contentObject) throws IOException {
final byte[] result;
switch (contentObject.type()) {
case PdfObject.INDIRECT:
PRIndirectReference ref = (PRIndirectReference) contentObject;
PdfObject directObject = PdfReader.getPdfObject(ref);
result = getContentBytesFromContentObject(directObject);
break;
case PdfObject.STREAM:
PRStream stream = (PRStream) PdfReader.getPdfObject(contentObject);
result = PdfReader.getStreamBytes(stream);
break;
case PdfObject.ARRAY:
// Stitch together all content before calling processContent(),
// because
// processContent() resets state.
ByteArrayOutputStream allBytes = new ByteArrayOutputStream();
PdfArray contentArray = (PdfArray) contentObject;
for (PdfObject pdfObject : contentArray.getElements()) {
allBytes.write(getContentBytesFromContentObject(pdfObject));
}
result = allBytes.toByteArray();
break;
default:
throw new IllegalStateException("Unable to handle Content of type " + contentObject.getClass());
}
return result;
return PdfContentStreamHandler.getContentBytesFromPdfObjectStatic(contentObject);
}

/**
Expand Down
Loading