Suppose that I have two instances layer1 and layer2 of type com.itextpdf.text.pdf.PdfLayer, with layer1 will be used for an instance of typecom.itextpdf.text.pdf.PdfTemplatethat contains a instance of type com.itextpdf.text.Image and layer2 will be used for a 3D annotation of type com.itextpdf.text.pdf.PdfAnnotation.
The problem: after setting the visibility and activating the area reserved for layer2, I can neither make it(layer2) unvisible nor displaying layer1.
Essential Code:
private Document document;
private PdfWriter writer;
PdfContentByte upperLayer;
Rectangle box;
private PdfLayer view2D;
private PdfLayer view3D;
public static void main(String[] args) throws DocumentException, MalformedURLException, URISyntaxException, IOException
{
LayersWithDiffDimsDemo generator = new LayersWithDiffDimsDemo();
generator.setupResources();
generator.report();
generator.cleanupResources();
}
public void setupResources() throws DocumentException, IOException
{
document = new Document(PageSize.A4);
FileOutputStream outputStream = new FileOutputStream("layers_with_diff_dimensions.pdf");
writer = PdfWriter.getInstance(document, outputStream);
document.open();
upperLayer = writer.getDirectContent();
box = new Rectangle(26.0f, document.getPageSize().getHeight() - 455.0f, 550, document.getPageSize().getHeight() - 210.0f);
box.setBorder(Rectangle.BOX);
box.setBorderWidth(0.5f);
box.setBorderColor(new BaseColor(0xFF, 0x00, 0x00));
document.add(box);
PdfLayer views = PdfLayer.createTitle("Ansichtsmodi", writer);
view2D = new PdfLayer("2D", writer);
view2D.setOn(true);
view3D = new PdfLayer("3D", writer);
view3D.setOn(false);
views.addChild(view3D);
views.addChild(view2D);
ArrayList<PdfLayer> radio = new ArrayList<>();
radio.add(view3D);
radio.add(view2D);
writer.addOCGRadioGroup(radio);
}
public void report() throws URISyntaxException, MalformedURLException, IOException
{
try
{
// Output the dimension drawing
// teapot.jpg is a screen shot of the 3d model
Image imageIn2D = Image.getInstance("teapot.jpg");
imageIn2D.setAbsolutePosition((document.getPageSize().getWidth() - imageIn2D.getWidth()) / 2, 400.0f);
imageIn2D.setLayer(view2D);
upperLayer.addImage(imageIn2D, true);
try {
// The file name that contains the 3D Model
FileInputStream inputStream = new FileInputStream("teapot.u3d");
PdfStream stream3D = new PdfStream(inputStream, writer);
stream3D.put(PdfName.TYPE, new PdfName("3D"));
stream3D.put(PdfName.SUBTYPE, new PdfName("U3D"));
stream3D.flateCompress();
try {
PdfIndirectObject streamObject = writer.addToBody(stream3D);
stream3D.writeLength();
PdfDictionary dict3D = new PdfDictionary();
dict3D.put(PdfName.TYPE, new PdfName("3DView"));
dict3D.put(new PdfName("XN"), new PdfString("Default"));
dict3D.put(new PdfName("IN"), new PdfString("Unnamed"));
dict3D.put(new PdfName("MS"), PdfName.M);
dict3D.put(new PdfName("C2W"), new PdfArray(new float[]{1, 0, 0, 0, 0, -1, 0, 1, 0, 3, -235, 28}));
dict3D.put(PdfName.CO, new PdfNumber(235));
PdfIndirectObject dictObject = writer.addToBody(dict3D);
PdfAnnotation annot = new PdfAnnotation(writer, box);
annot.setLayer(view3D);
annot.put(PdfName.CONTENTS, new PdfString("3D Model"));
annot.put(PdfName.SUBTYPE, new PdfName("3D"));
annot.put(PdfName.TYPE, PdfName.ANNOT);
annot.put(new PdfName("3DD"), streamObject.getIndirectReference());
annot.put(new PdfName("3DV"), dictObject.getIndirectReference());
PdfAppearance ap = upperLayer.createAppearance(box.getWidth(), box.getHeight());
annot.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, ap);
annot.setPage();
upperLayer.addAnnotation(annot, false);
} catch (IOException ex) {
Logger.getLogger(LayersWithDiffDimsDemo.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (FileNotFoundException ex) {
Logger.getLogger(LayersWithDiffDimsDemo.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (DocumentException ex)
{
Logger.getLogger(LayersWithDiffDimsDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void cleanupResources()
{
document.close();
}
Thank you for any suggests!
Assuming your viewer is Acrobat or Reader, as long as the 3D annotation is active it's going to be visible. The fact that the annot is associated with a layer, visible or otherwise, won't change that.
Defending my assertion...
Open the file at http://practicalpdf.com/downloads/BrakeAssembly.pdf.
The file has a single 3D Annotation taking up the whole page and is set to activate when clicked. It's deactivated when the file first opens. The 3D annot is also on a layer called "3DAnnot" and the file initial view is set to open in Reader with the layers panel showing. Associating an annotation with a layer is supported in the PDF Specification but there's no way to author it in Acrobat without a plugin or via a library as you are doing.
Notice when you first open the file, the 3D annotation is not active and you can toggle the layer visibility. Notice that the annotation poster visibility is following the layer visibility. Now activate the annot by clicking on it. Now notice that the activated 3D Annot is not affected by the visibility of the layer.
This is because layer visibility only applies to PDF Page content. The poster (appearance) of the 3D annot is the only part of that dictionary that is page content. The 3D viewer runtime is simply projecting into the same rectangle as the annot. While active, the 3D will always display over the page content even if you add a layer on top of the one that holds the 3D annotation.
Related
I need to add the total page count to a PDF/A-2 document created using iText in Java. The following code is being used:
public class HeaderFooterPageEvent extends PdfPageEventHelper {
Font fontHEADER = null;
/** The template with the total number of pages. */
PdfTemplate total;
public HeaderFooterPageEvent() {
try {
fontHEADER = new Font(BaseFont.createFont("OpenSans-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED), 8, Font.BOLD);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onOpenDocument(PdfWriter writer, Document document) {
total = writer.getDirectContent().createTemplate(30, 16);
super.onOpenDocument(writer, document);
}
#Override
public void onCloseDocument(PdfWriter writer, Document document) {
PdfContentByte cb = writer.getDirectContent();
ColumnText.showTextAligned(total, Element.ALIGN_RIGHT,
new Phrase(String.valueOf(writer.getPageNumber() - 1)),fontHEADER),
document.right() - document.rightMargin()+5,
document.bottom() - 10, 0);
super.onCloseDocument(writer, document);
}
}
And when creating the PDF the following code is called:
Document document = new Document(PageSize.A4, 15, 15, 30, 20);
PdfAWriter writer = PdfAWriter.getInstance(document, new FileOutputStream(dest), PdfAConformanceLevel.PDF_A_2A);
writer.createXmpMetadata();
writer.setTagged();
// add header and footer
HeaderFooterPageEvent event = new HeaderFooterPageEvent();
writer.setPageEvent(event);
document.open();
document.addLanguage("en-us");
File file = new File("sRGB_CS_profile.icm");
ICC_Profile icc = ICC_Profile
.getInstance(new FileInputStream(file));
writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
Paragraph p=new Paragraph("Page 1 content",fontEmbedded); //setting an embedded font
p.setSpacingBefore(30f);
document.add(p);
document.newPage();
document.add(new Paragraph("Content of next page goes here",fontEmbedded));
document.close();
Now when we add content on 2 pages and use document.newPage() to add the new page, runtime exception is generated The page 3 was requested but the document has only 2 pages. What is a solution to this problem?
I am using zest to create plugin that show graph. I am trying to create button that refresh the plugin. The button is working, and I see the graph in the view also. But, the button is taking a lot of space in the view, and limit the place for the graph.I want that the button want limit the graph place.. How can I fix it? Thanks]
public void createPartControl(Composite parent) {
//create refresh button
Composite container = new Composite(parent, SWT.NONE);
container.setLayout(new GridLayout(1, false));
Button btnMybutton = new Button(container, SWT.PUSH);
btnMybutton.setBounds(0, 10, 75, 25);
btnMybutton.setText("Refresh Graph");
btnMybutton.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent e) {
init();
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
// Graph will hold all other objects
graph = new Graph(parent, SWT.NONE);
}
If you want to show the button on top of the graph, you should use a FormLayout instead of a GridLayout:
public void createPartControl(Composite parent) {
//create refresh button
Composite container = new Composite(parent, SWT.NONE);
container.setLayout(new FormLayout()); // Use FormLayout instead of GridLayout
Button btnMybutton = new Button(container, SWT.PUSH);
// btnMybutton.setBounds(0, 10, 75, 25); This line is unnecessary
// Assign the right FormData to the button
FormData formData = new FormData();
formData.left = new FormAttachment(0, 5);
formData.top = new FormAttachment(0, 5);
btnMybutton.setLayoutData(formData);
btnMybutton.setText("Refresh Graph");
// Use SelectionAdapter instead of SelectionListener
// (it's not necessary but saves a few lines of code)
btnMybutton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
init();
}
});
// Graph will hold all other objects
graph = new Graph(container, SWT.NONE); // Note parent changed to container
// Assignt the right FormData to the graph
FormData formData2 = new FormData();
formData2.left = new FormAttachment(0, 0);
formData2.top = new FormAttachment(0, 0);
formData2.right = new FormAttachment(100, 0);
formData2.bottom = new FormAttachment(100, 0);
graph.setLayoutData(formData2);
}
I need to analyze path data of PDF files and manipulate content with iText 7. Manipulations include deletion/replacemant and coloring.
I can analyze the graphics alright with something like the following code:
public class ContentParsing {
public static void main(String[] args) throws IOException {
new ContentParsing().inspectPdf("testdata/test.pdf");
}
public void inspectPdf(String path) throws IOException {
File file = new File(path);
PdfDocument pdf = new PdfDocument(new PdfReader(file.getAbsolutePath()));
PdfDocumentContentParser parser = new PdfDocumentContentParser(pdf);
for (int i=1; i<=pdf.getNumberOfPages(); i++) {
parser.processContent(i, new PathEventListener());
}
pdf.close();
}
}
public class PathEventListener implements IEventListener {
public void eventOccurred(IEventData eventData, EventType eventType) {
PathRenderInfo pathRenderInfo = (PathRenderInfo) eventData;
for ( Subpath subpath : pathRenderInfo.getPath().getSubpaths() ) {
for ( IShape segment : subpath.getSegments() ) {
// Here goes some path analysis code
System.out.println(segment.getBasePoints());
}
}
}
public Set<EventType> getSupportedEvents() {
Set<EventType> supportedEvents = new HashSet<EventType>();
supportedEvents.add(EventType.RENDER_PATH);
return supportedEvents;
}
}
Now, what's the way to go with manipulating things and writing them back to the PDF? Do I have to construct an entirely new PDF document and copy everything over (in manipulated form), or can I somehow manipulate the read PDF data directly?
Now, what's the way to go with manipulating things and writing them back to the PDF? Do I have to construct an entirely new PDF document and copy everything over (in manipulated form), or can I somehow manipulate the read PDF data directly?
In essence you are looking for a class which is not merely parsing a PDF content stream and signaling the instructions in it like the PdfCanvasProcessor (the PdfDocumentContentParser you use is merely a very thin wrapper for PdfCanvasProcessor) but which also creates the content stream anew with the instructions you forward back to it.
A generic content stream editor class
For iText 5.5.x a proof-of-concept for such a content stream editor class can be found in this answer (the Java version is a bit further down in the answer text).
This is a port of that proof-of-concept to iText 7:
public class PdfCanvasEditor extends PdfCanvasProcessor
{
/**
* This method edits the immediate contents of a page, i.e. its content stream.
* It explicitly does not descent into form xobjects, patterns, or annotations.
*/
public void editPage(PdfDocument pdfDocument, int pageNumber) throws IOException
{
if ((pdfDocument.getReader() == null) || (pdfDocument.getWriter() == null))
{
throw new PdfException("PdfDocument must be opened in stamping mode.");
}
PdfPage page = pdfDocument.getPage(pageNumber);
PdfResources pdfResources = page.getResources();
PdfCanvas pdfCanvas = new PdfCanvas(new PdfStream(), pdfResources, pdfDocument);
editContent(page.getContentBytes(), pdfResources, pdfCanvas);
page.put(PdfName.Contents, pdfCanvas.getContentStream());
}
/**
* This method processes the content bytes and outputs to the given canvas.
* It explicitly does not descent into form xobjects, patterns, or annotations.
*/
public void editContent(byte[] contentBytes, PdfResources resources, PdfCanvas canvas)
{
this.canvas = canvas;
processContent(contentBytes, resources);
this.canvas = null;
}
/**
* <p>
* This method writes content stream operations to the target canvas. The default
* implementation writes them as they come, so it essentially generates identical
* copies of the original instructions the {#link ContentOperatorWrapper} instances
* forward to it.
* </p>
* <p>
* Override this method to achieve some fancy editing effect.
* </p>
*/
protected void write(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands)
{
PdfOutputStream pdfOutputStream = canvas.getContentStream().getOutputStream();
int index = 0;
for (PdfObject object : operands)
{
pdfOutputStream.write(object);
if (operands.size() > ++index)
pdfOutputStream.writeSpace();
else
pdfOutputStream.writeNewLine();
}
}
//
// constructor giving the parent a dummy listener to talk to
//
public PdfCanvasEditor()
{
super(new DummyEventListener());
}
//
// Overrides of PdfContentStreamProcessor methods
//
#Override
public IContentOperator registerContentOperator(String operatorString, IContentOperator operator)
{
ContentOperatorWrapper wrapper = new ContentOperatorWrapper();
wrapper.setOriginalOperator(operator);
IContentOperator formerOperator = super.registerContentOperator(operatorString, wrapper);
return formerOperator instanceof ContentOperatorWrapper ? ((ContentOperatorWrapper)formerOperator).getOriginalOperator() : formerOperator;
}
//
// members holding the output canvas and the resources
//
protected PdfCanvas canvas = null;
//
// A content operator class to wrap all content operators to forward the invocation to the editor
//
class ContentOperatorWrapper implements IContentOperator
{
public IContentOperator getOriginalOperator()
{
return originalOperator;
}
public void setOriginalOperator(IContentOperator originalOperator)
{
this.originalOperator = originalOperator;
}
#Override
public void invoke(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands)
{
if (originalOperator != null && !"Do".equals(operator.toString()))
{
originalOperator.invoke(processor, operator, operands);
}
write(processor, operator, operands);
}
private IContentOperator originalOperator = null;
}
//
// A dummy event listener to give to the underlying canvas processor to feed events to
//
static class DummyEventListener implements IEventListener
{
#Override
public void eventOccurred(IEventData data, EventType type)
{ }
#Override
public Set<EventType> getSupportedEvents()
{
return null;
}
}
}
(PdfCanvasEditor.java)
The explanations from the iText 5 answer still apply, the parsing framework has not changed much from iText 5.5.x to iText 7.0.x.
Usage examples
Unfortunately you wrote in very vague terms about how exactly you want to change the contents. Thus I simply ported some iText 5 samples which made use of the original iText 5 content stream editor class:
Watermark removal
These are ports of the use cases in this answer.
testRemoveBoldMTTextDocument
This example drops all text written in a font the name of which ends with "BoldMT":
try ( InputStream resource = getClass().getResourceAsStream("document.pdf");
PdfReader pdfReader = new PdfReader(resource);
OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "document-noBoldMTText.pdf"));
PdfWriter pdfWriter = new PdfWriter(result);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter) )
{
PdfCanvasEditor editor = new PdfCanvasEditor()
{
#Override
protected void write(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands)
{
String operatorString = operator.toString();
if (TEXT_SHOWING_OPERATORS.contains(operatorString))
{
if (getGraphicsState().getFont().getFontProgram().getFontNames().getFontName().endsWith("BoldMT"))
return;
}
super.write(processor, operator, operands);
}
final List<String> TEXT_SHOWING_OPERATORS = Arrays.asList("Tj", "'", "\"", "TJ");
};
for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++)
{
editor.editPage(pdfDocument, i);
}
}
(EditPageContent.java test method testRemoveBoldMTTextDocument)
testRemoveBigTextDocument
This example drops all text written with a large font size:
try ( InputStream resource = getClass().getResourceAsStream("document.pdf");
PdfReader pdfReader = new PdfReader(resource);
OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "document-noBigText.pdf"));
PdfWriter pdfWriter = new PdfWriter(result);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter) )
{
PdfCanvasEditor editor = new PdfCanvasEditor()
{
#Override
protected void write(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands)
{
String operatorString = operator.toString();
if (TEXT_SHOWING_OPERATORS.contains(operatorString))
{
if (getGraphicsState().getFontSize() > 100)
return;
}
super.write(processor, operator, operands);
}
final List<String> TEXT_SHOWING_OPERATORS = Arrays.asList("Tj", "'", "\"", "TJ");
};
for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++)
{
editor.editPage(pdfDocument, i);
}
}
(EditPageContent.java test method testRemoveBigTextDocument)
Text color change
This is a port of the use case in this answer.
testChangeBlackTextToGreenDocument
This example changes the color of black text to green.
try ( InputStream resource = getClass().getResourceAsStream("document.pdf");
PdfReader pdfReader = new PdfReader(resource);
OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "document-blackTextToGreen.pdf"));
PdfWriter pdfWriter = new PdfWriter(result);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter) )
{
PdfCanvasEditor editor = new PdfCanvasEditor()
{
#Override
protected void write(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands)
{
String operatorString = operator.toString();
if (TEXT_SHOWING_OPERATORS.contains(operatorString))
{
if (currentlyReplacedBlack == null)
{
Color currentFillColor = getGraphicsState().getFillColor();
if (Color.BLACK.equals(currentFillColor))
{
currentlyReplacedBlack = currentFillColor;
super.write(processor, new PdfLiteral("rg"), Arrays.asList(new PdfNumber(0), new PdfNumber(1), new PdfNumber(0), new PdfLiteral("rg")));
}
}
}
else if (currentlyReplacedBlack != null)
{
if (currentlyReplacedBlack instanceof DeviceCmyk)
{
super.write(processor, new PdfLiteral("k"), Arrays.asList(new PdfNumber(0), new PdfNumber(0), new PdfNumber(0), new PdfNumber(1), new PdfLiteral("k")));
}
else if (currentlyReplacedBlack instanceof DeviceGray)
{
super.write(processor, new PdfLiteral("g"), Arrays.asList(new PdfNumber(0), new PdfLiteral("g")));
}
else
{
super.write(processor, new PdfLiteral("rg"), Arrays.asList(new PdfNumber(0), new PdfNumber(0), new PdfNumber(0), new PdfLiteral("rg")));
}
currentlyReplacedBlack = null;
}
super.write(processor, operator, operands);
}
Color currentlyReplacedBlack = null;
final List<String> TEXT_SHOWING_OPERATORS = Arrays.asList("Tj", "'", "\"", "TJ");
};
for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++)
{
editor.editPage(pdfDocument, i);
}
}
(EditPageContent.java test method testChangeBlackTextToGreenDocument)
I have a requirement to do below items,
Read the existing PDF file
Search the specific keywords in the PDF
Highlight them in specific color or bold
Save the PDF
and i have to tried below code,
public static void main(String[] args) throws IOException, DocumentException
{
File file = new File(DEST); file.getParentFile().mkdirs();
new BrefingPackageHighlight_Main2().manipulatePdf(SRC, DEST);
}
public void manipulatePdf(String src, String dest) throws IOException, DocumentException
{
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest)); PdfContentByte canvas = stamper.getOverContent(2); canvas.saveState(); canvas.setColorFill(BaseColor.YELLOW);
canvas.rectangle(200, 786, 5, 5);
canvas.fill();
canvas.restoreState();
stamper.close();
reader.close();
}
the above code only highlights top of the second page. Please provide me samples to search one specific keyword and highlight them alone.
Please find the below code.
public class MakingFieldReadOnly implements PdfPCellEvent {
/** The resulting PDF. */
public static final String RESULT1 = "text_fields.pdf";
/** The resulting PDF. */
public static final String RESULT2 = "text_filled.pdf";
/** The text field index of a TextField that needs to be added to a cell. */
protected int tf;
public static final String CONTENT = "Write any thing so that it exceeds the content limit of the textfield and scroll bar comes. asdadasdasdasdasdasdasdasdasddlfjklfjljdflkjasdfjasdfjsldfjlsdjflsjdfljdflkjsdfljsldfjlsdjflskdfjlskdfjlsdjflskdjflksdjflksdjflkjsdflkjsdfljsdfkljsdlfjlsdjkfasdadasdasdasdasdasdasdasdasddlfjklfjljdflkjasdfjasdfjsldfjlsdjflsjdfljdflkjsdfljsldfjlsdjflskdfjlskdfjlsdjflskdjflksdjflksdjflkjsdflkjsdfljsdfkljsdlfjlsdjkfasdadasdasdasdasdasdasdasdasddlfjklfjljdflkjasdfjasdfjsldfjlsdjflsjdfljdflkjsdfljsldfjlsdjflskdfjlskdfjlsdjflskdjflksdjflksdjflkjsdflkjsdfljsdfkljsdlfjljkf";
/**
* Creates a cell event that will add a text field to a cell.
* #param tf a text field index.
*/
public MakingFieldReadOnly(int tf) {
this.tf = tf;
}
/**
* Manipulates a PDF file src with the file dest as result
* #param src the original PDF
* #param dest the resulting PDF
* #throws IOException
* #throws DocumentException */
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
AcroFields form = stamper.getAcroFields();
form.setField("text1_1", CONTENT);
form.setField("text1_2", CONTENT);
form.setField("text1_3", CONTENT);
form.setField("text1_4", CONTENT);
form.setFieldProperty("text1_1","setfflags",TextField.READ_ONLY , null);
form.setFieldProperty("text1_2","setfflags",TextField.READ_ONLY , null);
form.setFieldProperty("text1_3","setfflags",TextField.READ_ONLY , null);
form.setFieldProperty("text1_4","setfflags",TextField.READ_ONLY , null);
stamper.close();
//reader.close();
}
/**
* Creates a PDF document.
* #param filename the path to the new PDF document
* #throws DocumentException
* #throws IOException
*/
public void createPdf(String filename) throws DocumentException, IOException {
// step 1
Document document = new Document();
// step 2
PdfWriter.getInstance(document, new FileOutputStream(filename));
// step 3
document.open();
// step 4
PdfPCell cell;
PdfPTable table = new PdfPTable(2);
table.setWidths(new int[]{ 1, 2 });
table.addCell("Name:");
cell = new PdfPCell();
cell.setCellEvent(new MakingFieldReadOnly(1));
cell.setFixedHeight(60);
table.addCell(cell);
table.addCell("Loginname:");
cell = new PdfPCell();
cell.setCellEvent(new MakingFieldReadOnly(2));
cell.setFixedHeight(60);
table.addCell(cell);
table.addCell("Password:");
cell = new PdfPCell();
cell.setCellEvent(new MakingFieldReadOnly(3));
cell.setFixedHeight(60);
table.addCell(cell);
table.addCell("Reason:");
cell = new PdfPCell();
cell.setCellEvent(new MakingFieldReadOnly(4));
cell.setFixedHeight(60);
table.addCell(cell);
document.add(table);
// step 5
document.close();
}
/**
* Creates and adds a text field that will be added to a cell.
* #see com.itextpdf.text.pdf.PdfPCellEvent#cellLayout(com.itextpdf.text.pdf.PdfPCell,
* com.itextpdf.text.Rectangle, com.itextpdf.text.pdf.PdfContentByte[])
*/
public void cellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
TextField text = new TextField(writer, rectangle, String.format("text1_%s",tf));
text.setBackgroundColor(new GrayColor(0.75f));
text.setOptions(TextField.MULTILINE | TextField.REQUIRED);
text.setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
text.setFontSize(8);
try {
PdfFormField field = text.getTextField();
writer.addAnnotation(field);
}
catch(IOException ioe) {
throw new ExceptionConverter(ioe);
}
catch(DocumentException de) {
throw new ExceptionConverter(de);
}
}
/**
* Main method
* #param args no arguments needed
* #throws IOException
* #throws DocumentException
*/
public static void main(String[] args) throws DocumentException, IOException {
MakingFieldReadOnly example = new MakingFieldReadOnly(0);
example.createPdf(RESULT1);
example.manipulatePdf(RESULT1, RESULT2);
}
}
Please run the above code and generate the document. I have used itext-1.3.jar but same behavior shown with itext-5.3.5.jar.
In the second file named as "text_filled.pdf", I have four pdf cells(fields) in the table. My code is making these editable fields read only but I want scroll bar also(when content exceeds the field limit) as like it is coming for 4th one only, so that user can be able to view whole content without having edit permission.
Could I get read only mode with scroll bar(if content is more than limit of the text field) for each cell of the the table.
I have tried the below code also for making the fields read only.
form.setFieldProperty("text1_1","setfflags",PdfFormField.FF_READ_ONLY , null);
form.setFieldProperty("text1_2","setfflags",PdfFormField.FF_READ_ONLY , null);
form.setFieldProperty("text1_3","setfflags",PdfFormField.FF_READ_ONLY, null);
form.setFieldProperty("text1_4","setfflags",PdfFormField.FF_READ_ONLY , null);
If from these codes can't be done then any other possible solution.
I have tried your example, and I have discovered that the behavior you experience is caused by a bug in Adobe Acrobat / Reader. The bug occurs when the borders of the widget annotations of different text fields overlap.
Once I made sure that there was no overlap between the different fields, the scroll bars appeared.
How did I make sure that there was no overlap? Simply by changing the way the TextField instance created in your cellLayout() method:
Rectangle rect = new Rectangle(
rectangle.getLeft(), rectangle.getTop() - 1,
rectangle.getRight(), rectangle.getBottom() + 1);
TextField text = new TextField(writer, rect, String.format("text1_%s",tf));
Now the rectangles that define the text field no longer overlap, and you no longer experience the Adobe Acrobat / Reader bug.