I have code which has worked for some time to stamp 'DRAFT' over the pages of a PDF file
I just updated the app to the 5.5.5 jar and for some PDFs instead of lovely pink watermark it is only black. The code works properly for both source files with 5.5.3, and not for the second with 5.5.4 as the second source is tagged (due to the background letterhead file - issue introduced which throws a NullPointerError) and now not with 5.5.5 either (no error but undesired result)
It works with a simple 'hello world' example but not other files created from iText
file eg_01 and eg_o1A show working example, 1B and 1C show not working example
Stamping code snippet in Groovy
import com.itextpdf.text.Element
import com.itextpdf.text.BaseColor
import com.itextpdf.text.pdf.BaseFont
import com.itextpdf.text.pdf.PdfStamper
import com.itextpdf.text.pdf.PdfReader
today = new Date()
reader = new PdfReader(source)
stamper = new PdfStamper(reader, new FileOutputStream(output))
bf = BaseFont.createFont(BaseFont.HELVETICA_BOLD, BaseFont.WINANSI, BaseFont.EMBEDDED)
tSize = 24
mark = 'DRAFT ' + today.format('dd/MM/yyyy')
angle = 45
height = reader.getPageSizeWithRotation(1).getHeight()/2
width = reader.getPageSizeWithRotation(1).getWidth()/2
cb = stamper.getOverContent(1)
cb.setColorFill(new BaseColor(255,200,200))
cb.setFontAndSize(bf, tSize)
cb.beginText()
cb.showTextAligned(Element.ALIGN_CENTER, mark, width.toFloat(), height.toFloat(), angle)
cb.endText()
stamper.close()
reader.close()
return true
Related
I'm using iTextSharp 5.5.13 and when i try to generate the PDF with Hebrew it comes out empty.
this is my code: I'm i doing something wrong?
public byte[] GenerateIvhunPdf(FinalIvhunSolution ivhun)
{
byte[] pdfBytes;
using (var mem = new MemoryStream())
{
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.GetInstance(document, mem);
writer.PageEvent = new MyHeaderNFooter();
document.Open();
var font = new
Font(BaseFont.CreateFont("C:\\Downloads\\fonts\\Rubik-Light.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED), 14);
Paragraph p = new Paragraph("פסקת פתיחה")
{
Alignment = Element.ALIGN_RIGHT
};
PdfPTable table = new PdfPTable(2)
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL
};
PdfPCell cell = new PdfPCell(new Phrase("מזהה", font));
cell.BackgroundColor = BaseColor.BLACK;
table.AddCell(cell);
document.Add(p);
document.Add(table);
document.Close();
pdfBytes = mem.ToArray();
}
return pdfBytes;
}
The PDF comes out blank
I changed a few details of your code, and now I get this:
My changes:
Embedding the font
As I don't have Rubik installed on my system, I have to embed the font into the PDF to have a chance to see anything. Thus, I replaced BaseFont.NOT_EMBEDDED by BaseFont.EMBEDDED when creating the var font:
var font = new Font(BaseFont.CreateFont("Rubik-Light.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED), 14);
Making the Paragraph kind of work
You create the Paragraph p without specifying a font. Thus, a default font with default encoding is used. The default encoding is WinAnsiEncoding which is Latin1-like, so no Hebrew characters can be represented. I added your Rubik font instance to the Paragraph p creation:
Paragraph p = new Paragraph("פסקת פתיחה", font)
{
Alignment = Element.ALIGN_RIGHT
};
Et voilà, the writing appears.
iText developers often have communicated that in iText 5.x and earlier right-to-left scripts are only supported properly in certain contexts, e.g. in tables, but not in others like paragraphs immediately added to the document. As your Paragraph p is added immediately to the Document document, its letters appear in the wrong order in the output.
Making the PdfPTable work
You defined the PdfPTable table to have two columns (new PdfPTable(2)) but then you added only one cell. Thus, table contains not even a single complete row. iText, therefore, draws nothing when it is added to the document.
I changed the definition of table to have a single column only:
PdfPTable table = new PdfPTable(1)
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL
};
Furthermore, I commented out the line setting the cell background to black because usually it is difficult to read black on black:
PdfPCell cell = new PdfPCell(new Phrase("מזהה", font));
//cell.BackgroundColor = BaseColor.BLACK;
table.AddCell(cell);
And again the writing appears.
Properly downloading the font
Another possible obstacle is that when downloading the font from the URL you gave — https://fonts.google.com/selection?selection.family=Rubik — one can see in the customization tab of the selection drawer that by default only Latin characters are included in the download, in particular not Hebrew ones:
I tested with a font file I downloaded with all language options enabled:
let's say I have a bunch of pdf files that I want to migrate into a new pdf. BUT the new pdf file is a table-structured file. And the content of the pdf files should fit in the first cell of a two-column-table.
I am not sure if the approach of working with tables is correct. I am open to any other solutions. All I want is at the end some custom text at the top, followed by pdf content and a checkbox on the right side. (One per pdf content)
What I have so far:
`
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc, PageSize.A4);
doc.SetMargins(0f, 0f, 18f, 18f);
PdfReader reader = new PdfReader(src);
PdfDocument srcDoc = new PdfDocument(reader);
Table table = new Table(new float[] { 2f, 1f });
PdfFormXObject imagePage = srcDoc.GetFirstPage().CopyAsFormXObject(pdfDoc);
var image = new Image(imagePage);
Cell cell = new Cell().Add(image);
cell.SetHorizontalAlignment(HorizontalAlignment.LEFT);
cell.SetVerticalAlignment(VerticalAlignment.TOP);
table.AddCell(cell);
Table checkTable = new Table(2);
Cell cellCheck1 = new Cell();
cellCheck1.SetNextRenderer(new CheckboxCellRenderer(cellCheck1, "cb1", 0));
cellCheck1.SetHeight(50);
checkTable.AddCell(cellCheck1);
Cell cellCheck2 = new Cell();
cellCheck2.SetNextRenderer(new CheckboxCellRenderer(cellCheck2, "cb2", 1));
cellCheck2.SetHeight(50);
checkTable.AddCell(cellCheck2);
table.AddCell(checkTable);
doc.Add(table);
doc.Close();`
My Problem here is that the pdf content has still its margin. Which completely spoils the design. It is so frustrating, I appreciate any help.
You say
My Problem here is that the pdf content has still its margin. Which completely spoils the design.
PDFs (usually) don't know anything about margins. Thus, you have to detect the margins of the page to import first. You can do this by parsing the page content into an event listener that keeps track of the bounding box of drawing instructions, like the TextMarginFinder. Then you can reduce the source page to those dimensions. This can be done by means of the following method:
PdfPage restrictToText(PdfPage page)
{
TextMarginFinder finder = new TextMarginFinder();
new PdfCanvasProcessor(finder).ProcessPageContent(page);
Rectangle textRect = finder.GetTextRectangle();
page.SetMediaBox(textRect);
page.SetCropBox(textRect);
return page;
}
You apply this method in your code right before you copy the page as form XObject, i.e. you replace
PdfFormXObject imagePage = srcDoc.GetFirstPage().CopyAsFormXObject(pdfDoc);
by
PdfFormXObject imagePage = restrictToText(srcDoc.GetFirstPage()).CopyAsFormXObject(pdfDoc);
This causes the Image this XObject will be embedded in to have the correct size. Unfortunately it will be somewhat mispositioned because the restricted page still has the same coordinate system as the original one, merely its crop box defines a smaller section than before. To fix this, one has to apply an offset, one has to subtract the coordinates of the lower left corner of the page crop box which has become the XObject bounding box. Thus, add after instantiating the Image the following code:
Rectangle bbox = imagePage.GetBBox().ToRectangle();
image.SetProperty(Property.LEFT, -bbox.GetLeft());
image.SetProperty(Property.BOTTOM, -bbox.GetBottom());
image.SetProperty(Property.POSITION, LayoutPosition.RELATIVE);
Now the restricted page is properly positioned in your table cell.
Beware: The TextMarginFinder (as its name indicates) determines the margins by text alone. Thus, if the page contains other contents, too, e.g. decorations like a logo, this logo is ignored and might eventually be cut out. If you want such decorations, too, in your overviews, you have to use a different margin finder class.
i want to align the Chunk Left and Right side. Also the each Chunk have different format you can see in image.
i try the below code:
Chunk invoiceid = new Chunk("Invoice ID: ", font9BoldDARK_GRAY);
Chunk invoiceidvalue = new Chunk("value from database", font10NoramlBlack);
Chunk inoicdate = new Chunk("Invoice Date: ", font9BoldDARK_GRAY);
Chunk inoicedatevalue = new Chunk(new SimpleDateFormat("MMMM dd yyyy").format(new Date()), font10NoramlBlack);// get From database
Paragraph invoiceParagraph = new Paragraph();
invoiceParagraph.setTabSettings(new TabSettings(325f));
invoiceParagraph.add(invoiceid);
invoiceParagraph.add(invoiceidvalue);
invoiceParagraph1.add(Chunk.TABBING);
invoiceParagraph1.add(inoicdate1);
invoiceParagraph1.add(inoicedatevalue1);
invoiceParagraph1.setAlignment(Element.ALIGN_JUSTIFIED);
pdfdocument.add(invoiceParagraph1);
which gives me result the Right side Chunk not in well format.
but i want align the like
can you please help me.
The correct way to do this, is to use iText 7. Read chapter 3 of the building blocks tutorial to discover how to create a PDF that looks like this:
The code to achieve this, is amazingly simple:
public void createPdf(String dest) throws IOException {
// create a low-level document
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
// create a high-level document
Document document = new Document(pdf);
// create a TabStop array
List<TabStop> tabstops = new ArrayList<TabStop>();
// don't forget to make a tab stop that aligns to the right
tabstops.add(new TabStop(325, TabAlignment.RIGHT));
// add paragraphs with Tab objects to the high-level document
document.add(new Paragraph().addTabStops(tabstops)
.add("Text to the left").add(new Tab()).add("Text to the right"));
document.add(new Paragraph().addTabStops(tabstops)
.add("ABCD").add(new Tab()).add("EFGH"));
document.add(new Paragraph().addTabStops(tabstops)
.add("01234").add(new Tab()).add("56789"));
document.add(new Paragraph().addTabStops(tabstops)
.add("iText 5 is old").add(new Tab()).add("iText 7 is new"));
// close the document
document.close();
}
Before you say I don't recognize that code, let me tell you that you are right: iText was completely rewritten. The code is now more intuitive to create, and easier to read.
Update: you are using the old iText 5 version that is no longer supported for free users (only for paying customers). As explained in the 2009 book "iText in Action - Second Edition", you created glue like this:
Chunk glue = new Chunk(new VerticalPositionMark())
You then used this glue in a Paragraph like this:
Paragraph p = new Paragraph();
p.add("Text to the left");
p.add(glue);
p.add("Text to the right");
This way, you can indeed avoid having to use tabs in iText 5.
this work for me:
Paragraph p = new Paragraph("some Text");
p.setAlignment(Element.ALIGN_RIGHT);
I seem to have an issue after upgrading iText from 2.1.7 where the PDF seems to be missing or the image has shrunk between pages.
I'm wondering if this is a known issue or if there is something that I need to set in order to fix it.
Some context:
no real calculations have been changed when switching libraries.
the general structure is that we have a Document which has a pdfTable which holds a bunch of pdfImages.
changing between landscape and portrait produces different results.
the images are scaled down so that it will fit the page.
Edit: Sorry, my application was pretty big and does a bunch of work. I had to make a simple mock version before posting the problem
Sample Code (So the numbers are just examples that I used. I basically added a 800*600 Image 5 times using landscape position. I end up seeing only 3 pages when I am expecting 5.)
Note: Using portrait page size shows all 5 but it seems that the sizes vary for some reason.
ByteArrayOutputStream baos = createTemporaryOutputStream();
Document doc = newDocument();
PdfWriter writer = newWriter(doc, baos);
writer.setViewerPreferences(PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage);
//create page rectangle landscape
Rectangle page = new Rectangle(PageSize.A4.rotate());
doc.setPageSize(page);
doc.setMargins((float)36.0, (float)36.0, (float)36.0, (float)36.0);
doc.open();
//create element pdf table.
PdfPTable table = new PdfPTable(new float[]{(float) 770.0});
table.setWidthPercentage(100);
table.setSplitRows(true);
table.setSplitLate(false);
table.setHeaderRows(0);
// in my case I used 5 800*600 images (same picture)
//then I loop through them and create pdfcell
//and then add it to table which then gets added to the document
List<Image> hi = (List<Image>) model.get("images");
for (Image image : hi) {
com.itextpdf.text.Image pdfImage = com.itextpdf.text.Image.getInstance(image.getBytes());
pdfImage.scalePercent((float) (0.8642384 * 100));
PdfPCell cell = new PdfPCell(pdfImage, false);
table.addCell(cell);
}
doc.add(table);
doc.close();
I have a pdf which include text written in Type 3 Font.
I want to get some text from it and write it into other pdf in exactly same shape.
I am using itext. Please give me a tip.
edit: I attached my code.
DocumentFont f = renderInfo.getFont();
String str = renderInfo.getText();
x = renderInfo.getBaseline().getStartPoint().get(Vector.I1);
In this code, I want to write str into x value position.
In Type 3 Font, is it work?
You can copy parts of one page to a new one using code like this:
InputStream resourceStream = getClass().getResourceAsStream("from.pdf");
PdfReader reader = new PdfReader(new FileOutputStream("from.pdf"));
Rectangle pagesize = reader.getPageSizeWithRotation(1);
Document document = new Document(pagesize);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("areaOfFrom.pdf"));
document.open();
PdfContentByte content = writer.getDirectContent();
PdfImportedPage page = writer.getImportedPage(reader, 1);
content.saveState();
content.rectangle(0, 350, 360, 475);
content.clip();
content.newPath();
content.addTemplate(page, 0, 0);
content.restoreState();
document.close();
reader.close();
This turns your
into
Unfortunately, though, that hidden content is merely... hidden... but it is still there. You can especially mark the lines with that hidden text and try to copy&paste them.
If you want to completely remove that hidden text (or start out by merely copying the desired text), you have to inspect the content of the imported page and filter it. I'm afraid iText does not yet explicitly support something like that. It can be done using the iText lowlevel API but it is quite some work.