iText 7 can not set margin - java

I have an HTML string, i need to convert it to pdf, but pdf that i need must have specific size and margin. I did as the example show, now i have pdf with width and height that i set, BUT i can`t change or delete the margin, so pls help me.
using (FileStream fs = new FileStream(somePDFFile, FileMode.OpenOrCreate, FileAccess.Write))
{
iText.Kernel.Pdf.PdfWriter pdfWriter = new iText.Kernel.Pdf.PdfWriter(fs);
iText.Kernel.Pdf.PdfDocument pdfDoc = new iText.Kernel.Pdf.PdfDocument(pdfWriter);
var v = pdfDoc.GetDefaultPageSize().ApplyMargins<iText.Kernel.Geom.Rectangle>(1, 1, 1, 1, true);
pdfDoc.GetDefaultPageSize().SetWidth(250f);
pdfDoc.GetDefaultPageSize().SetHeight(200f);
pdfDoc.GetCatalog().SetLang(new iText.Kernel.Pdf.PdfString("en-US"));
//Set the document to be tagged
pdfDoc.SetTagged();
iText.Html2pdf.ConverterProperties props = new iText.Html2pdf.ConverterProperties();
iText.Html2pdf.HtmlConverter.ConvertToPdf(htmlString, pdfDoc, props);
pdfDoc.Close();
}

I searched for an answer, but I could only find this approach:
public void createPdf(String src, String dest) throws IOException {
ConverterProperties properties = new ConverterProperties();
properties.setBaseUri(new File(src).getParent());
List<IElement> elements =
HtmlConverter.convertToElements(new FileInputStream(src), properties);
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
pdf.setTagged();
Document document = new Document(pdf);
document.setMargins(100, 50, 50, 100);
for (IElement element : elements) {
document.add((IBlockElement)element);
}
document.close();
}
In other words: I convert the HTML to a list of elements, and I then add those elements to a Document for which I define a margin.
My preferred solution would have been to define the margin at the level of the <body> tag as done in How to margin the body of the page (html)? Unfortunately, I noticed that this isn't supported yet (and I made a ticket for the iText development team to fix this).
I also tried the convertToDocument() method, but I wasn't able to set immediateFlush to false. I also asked the team to look into this.
Maybe there's also a property that could be introduced, although I'm not all that sure if this should be a ConverterProperties property, a PdfDocument property, or a PdfWriter property.
Update:
You could use the #page rule in CSS to define the margins. For instance:
<style>
#page {
margin-top: 200pt;
}
</style>
This creates a PDF with a top margin of 200pt.

Related

How to remove in Java the Margin of page with iTexPdf using HTMLConverter

I tried, with padding: 0, margin 0 in the body, tried setting the doc() with setMargin but nothing works
Document.setMargins() doesn’t change the margin for already generated pages. Try to use setImmediateFlush and relayout() method as suggested below.
PdfWriter writer = new PdfWriter(ms);
PdfDocument pdfDocument = new PdfDocument(writer);
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.SetImmediateFlush(false);
//Pass the sample html file
Document document=HtmlConverter.ConvertToDocument(bodyHTML, pdfDocument,
converterProperties);
document.SetMargins(50, 50, 50, 50);
document.Relayout();
document.Close();

iText set up border color and width for check box, but it does not work

I want to use iText to add a check box to a PDF file, and here is my code:
public static void testPdf() throws IOException {
String src = "/Users/heartisan/Downloads/xx.pdf";
String dest = "/Users/heartisan/Downloads/yy.pdf";
PdfDocument pdf = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);
Document document = new Document(pdf);
for (int i = 0; i < 3; i++) {
PdfButtonFormField checkField = PdfFormField.createCheckBox(pdf, new Rectangle(369 + i * 69, 751, 15, 15),
"experience".concat(String.valueOf(i+1)), "Off", PdfFormField.TYPE_CHECK);
checkField.setBorderWidth(2);
checkField.setBorderColor(DeviceGray.GRAY);
checkField.setVisibility(PdfFormField.VISIBLE);
checkField.setBackgroundColor(ColorConstants.RED);
checkField.setToggleOff(false);
// checkField.getWidgets().get(0).setBorderStyle(PdfAnnotation.STYLE_SOLID);
form.addField(checkField, pdf.getPage(1));
}
document.close();
}
Then here is the result:
Actually, as the code showed before, I set up the border color and width, but it just not work, I used Adobe Arcobat and it works:
Then I debugged the two files' fields, and I found:
As I marked, both the color and width's values are gone, both the values were there just before I call document.close(), I don't know why.
Can anyone help me?
Is it expected result if you open your resultant PDF in Google Chrome or Pdf Studio 2020? I have the same result In Acrobat so I think it's not an issue of iText. Btw, If you click on your checkFields in Acrobat, all looks as expected.

IText7> How to add a content of PdfCanvas as PdfName.Figure for PDF/UA Accessibility

I would like to add an element in PdfCanvas, codes as below. Why I can't see the "Figure" in document tag?
PdfCanvas canvas = new PdfCanvas(pdf.addNewPage());
canvas.beginText();
canvas.setFontAndSize(font, 12);
canvas.showText("Test for Accessibility");
canvas.stroke();
PdfDictionary dict = new PdfDictionary();
dict.put(PdfName.Span, new PdfString("Eyes Wide Shut"));
canvas.beginMarkedContent(PdfName.Figure, dict);
canvas.newlineShowText("EWS");
canvas.endMarkedContent();
canvas.endText();
First of all your code is not complete so we don't even know if you call setTagged() on a PdfDocument instance (which is a must for tagging).
But the bigger problem is that beginMarkedContent on its own does not add any connections from the content to the tag tree. The best way to add those connections is use TagTreePointer (if you really want to use low-level PdfCanvas API). You can manipulate tree structure with TagTreePointer and add connections between tree and content with PdfCanvas#openTag.
Also, you seem to be trying to add expansion text (Eyes Wide Shut) with dict.put(PdfName.Span, new PdfString("Eyes Wide Shut"));, but from the PDF syntax point of view this expression does not do anything useful. TagTreePointer's API allows you to set expansion text easily as well.
All in all, the complete code would look like following:
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFilePath));
pdfDocument.setTagged();
PdfPage firstPage = pdfDocument.addNewPage();
PdfCanvas canvas = new PdfCanvas(firstPage);
TagTreePointer tagPointer = new TagTreePointer(pdfDocument);
tagPointer.setPageForTagging(firstPage);
tagPointer.addTag(StandardRoles.P).addTag(StandardRoles.SPAN);
canvas.beginText()
.setFontAndSize(PdfFontFactory.createFont(), 12)
.openTag(tagPointer.getTagReference())
.showText("Test for Accessibility")
.closeTag()
.stroke();
tagPointer.moveToParent().addTag(StandardRoles.SPAN).getProperties().setExpansion("Eyes Wide Shut");
canvas.openTag(tagPointer.getTagReference())
.newlineShowText("EWS")
.closeTag()
.endText();
pdfDocument.close();
The resultant tag structure:

Add text to a specific page of a pdf using iText

I need create a tool that adds a hyperlink every other page for a pdf file.
I followed the iText documentation and I managed to add the hyperlink but only on the first page.
My code:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
Font bold = new Font(FontFamily.HELVETICA, 30, Font.BOLD);
PdfReader reader = new PdfReader(src);
int count = reader.getNumberOfPages();
Utils.logInfoMessage("Number of pages: " + count, mLogList);
if(count < 1) {
Utils.logErrorMessage("file : " + src + " has no pages", mLogList);
return;
}
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
PdfContentByte canvas = stamper.getOverContent(1);
PdfGState gState = new PdfGState();
gState.setFillOpacity(0.1f);
canvas.setGState(gState);
Chunk chunk = new Chunk("www.google.com", bold);
chunk.setAnchor("https://www.google.ro/");
Phrase phrase = new Phrase("");
phrase.add(chunk);
ColumnText ct = new ColumnText(canvas);
ct.setSimpleColumn(36, 700, 559, 750);
ct.addText(phrase);
ct.go();
stamper.close();
reader.close();
}
Any ideas how to add the hyperlink/text only on a specific page?
You wrote:
I followed the iText documentation and I managed to add the hyperlink but only on the first page
This is the iText documentation: PdfStamper
getOverContent
public PdfContentByte getOverContent(int pageNum)
Gets a PdfContentByte to write over the page of the original
document.
Parameters:
pageNum - the page number where the extra content is written
Returns:
a PdfContentByte to write over the page of the original document
This is the code you wrote:
PdfContentByte canvas = stamper.getOverContent(1);
You used 1 as the value for pageNum.
Now you tell me: if you choose 1 as the page number, then why are you surprised that all the content you add is only added on the first page?
IMPORTANT:
You write
I followed the iText documentation
I assume that you refer to the official documentation on the official iText web page: https://itextpdf.com
If that is correct, then why are you still using an old version of iText? The current version is 7.1.2, and the PdfStamper class no longer exists in that version. As explained in chapter 5 of the iText 7 Jump-Start tutorial adding content to an existing PDF is done differently nowadays.
FYI: there are some more tutorials here: https://developers.itextpdf.com/books

iText: Importing styled Text and informations from an existing PDF

I´m generating PDFs using iText and it works fine. But I need a way to import html styled informations from an existing PDF at some point.
I know i could just use the XMLWorker class to generate the text directly from html in my own document. But cause I´m not sure whether it actually supports all html features I´m looking to work around this.
Therefore a PDF is generated from html using XSLT. The content of this PDF then should be copied to my document.
There are two ways discribed in the book ("iText in Action").
One that parses the PDF and gets you the text (or other informations) from the document using PdfReaderContentParser and TextExtractionStrategy.
It looks like this:
PdfReader reader = new PdfReader(pdf);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
TextExtractionStrategy strategy;
for(int i=1;i<=reader.getNumberOfPages();i++){
strategy = parser.processContent(i, new LocationTextExtractionStrategy());
document.add(new Chunk(strategy.getResultantText()));
}
But this only prints plain text to the document. Obviously there are more ExtractionStrategys and maybe one of them does exactly what i want but i couldn´t find it yet.
The second way is to copy an itextpdf.text.Image of each side of the PDF to your document. This is obviously not a good idea, cause it will add the entire page to your document even if there is only one line of text in the existing PDF. Its done like this:
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
PdfReader reader = new PdfReader(pdf);
PdfImportedPage page;
for(int i=1;i<=reader.getNumberOfPages();i++){
page = writer.getImportedPage(reader,i);
document.add(Image.getInstance(page));
}
Like I said this copys all the empty lines at the end of the PDF aswell, but i need to continue my text immediatly after the last line of text.
If I could convert this itext.text.Image into a java.awt.BufferedImage I could use getSubImage(); and informations i can extract from the PDF to cut away all the empty lines. But i wasn´t able to find a way to to this.
This are the two ways i found. But cause none of them is suitable for my purpose as they are my question is:
Is there a way to import everything except the empty lines at the end, but including text-style informations, tables and everything else from a PDF to my document using iText?
You can trim away empty space of the XSLT generated PDF and then import the trimmed pages as in your code.
Example code
The following code borrows from the code in my answer to Using iTextPDF to trim a page's whitespace. In contrast to the code there, though, we have to manipulate the media box, not the crop box, because this is the only box respected by PdfWriter.getImportedPage.
Before importing a page from a given PdfReader, crop it using this method:
static void cropPdf(PdfReader reader) throws IOException
{
int n = reader.getNumberOfPages();
for (int i = 1; i <= n; i++)
{
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
MarginFinder finder = parser.processContent(i, new MarginFinder());
Rectangle rect = new Rectangle(finder.getLlx(), finder.getLly(), finder.getUrx(), finder.getUry());
PdfDictionary page = reader.getPageN(i);
page.put(PdfName.MEDIABOX, new PdfArray(new float[]{rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop()}));
}
}
(excerpt from ImportPageWithoutFreeSpace.java)
The extended render listener MarginFinder is taken as is from the question linked to above. You can find a copy here: MarginFinder.java.
Example run
Using this code
PdfReader readerText = new PdfReader(docText);
cropPdf(readerText);
PdfReader readerGraphics = new PdfReader(docGraphics);
cropPdf(readerGraphics);
try ( FileOutputStream fos = new FileOutputStream(new File(RESULT_FOLDER, "importPages.pdf")))
{
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, fos);
document.open();
document.add(new Paragraph("Let's import 'textOnly.pdf'", new Font(FontFamily.HELVETICA, 12, Font.BOLD)));
document.add(Image.getInstance(writer.getImportedPage(readerText, 1)));
document.add(new Paragraph("and now 'graphicsOnly.pdf'", new Font(FontFamily.HELVETICA, 12, Font.BOLD)));
document.add(Image.getInstance(writer.getImportedPage(readerGraphics, 1)));
document.add(new Paragraph("That's all, folks!", new Font(FontFamily.HELVETICA, 12, Font.BOLD)));
document.close();
}
finally
{
readerText.close();
readerGraphics.close();
}
(excerpt from unit test method testImportPages in ImportPageWithoutFreeSpace.java)
I imported both the page from the docText document
and the page from the docGraphics document
into a new document with some text before, between, and after. The result:
As you can see, source styles are preserved but free space around is discarded.

Categories