ShowTextAligned is not outputting text accurately - itext

I'm using the code snippet below. I would expect the text to be exactly one inch apart but it's not. What am I doing wrong?
Dim outputFile As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf")
Using fs As New FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)
Using doc As New Document(PageSize.LETTER)
Using writer As PdfWriter = PdfWriter.GetInstance(doc, fs)
doc.Open()
'This creates two lines of text using the iTextSharp abstractions
' doc.Add(New Paragraph("This is Paragraph 1"))
' doc.Add(New Paragraph("This is Paragraph 2"))
'This does the same as above but line spacing needs to be calculated manually
Dim cb As PdfContentByte = writer.DirectContent
cb.SaveState()
cb.SetColorFill(BaseColor.BLACK)
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 12.0F)
cb.BeginText()
' rlm - dimensions are from the bottom
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "This is cb1", 20, 20, 0)
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "This is cb2", 20, 92, 0)
cb.EndText()
cb.RestoreState()
doc.Close()
End Using
End Using
End Using

I'm not sure how you are measuring things but I just printed your sample out at actual resolution and compared it with a ruler and their baselines are indeed one inch apart.
If you are measuring on a computer screen you are going to run into problems. Windows-based machines generally (although this is changing) run at 96 DPI, so if you view your test on a computer screen at 100% and try to measure it you'll get about 4/3 of an inch (96/72). So called "hi-DPI" settings and devices are becoming more commonplace so there's no guarantee what a screen will actually measure to.

Related

Why does Rotation change not change the crop box?

I want to crop / remove / cut away a part of a pdf page.
Somebody provided a code for me to do that in this question.
2 new problems occured:
I want to print the PDF in a different orientation
I want to cut away more of the blank space around the DHL label
Because dealing with the coordinates in iTextSharp requires (0,0) based coders to twist their mind a bit, I first wanted to rotate the PDF so that I can follow it along more easily.
I did that using the following code:
Dim testFile As String = "new pdf1.pdf"
Dim resultFile As String = "new pdf1-Rotated.pdf"
Using pdfReader As PdfReader = New PdfReader(testFile)
Using pdfStamper As PdfStamper = New PdfStamper(pdfReader, File.Create(resultFile))
For i As Integer = 1 To pdfReader.NumberOfPages
Dim rotate As Integer = pdfReader.GetPageRotation(i)
Dim pageDictionary As PdfDictionary = pdfReader.GetPageN(i)
pageDictionary.Put(PdfName.ROTATE, New PdfNumber(90))
Next
End Using
End Using
It does work.
I expected that the page rotation change would automatically affect the crop box.
However, it does not.
Dim testFile As String = "new pdf1.pdf" 'they both give the same cropbox
Dim testFile As String = "new pdf1-Rotated.pdf"'they both give the same cropbox
Using pdfReader As PdfReader = New PdfReader(testFile)
For i As Integer = 1 To pdfReader.NumberOfPages
Dim cropBox As Rectangle = pdfReader.GetCropBox(i)
Why is that so?

How to add inline spacing in pdfPCell

I need to add Space between two lines in iTextSharp pdfPCell
Chunk chunk = new Chunk("Received Rs(In Words) : " + " " + myDataTable.Tables[1].Rows[0]["Recieved"].ToString(), font8);
PdfPTable PdfPTable = new PdfPTable(1);
PdfPCell PdfPCell =new PdfPCell(new Phrase(Chunk ));
PdfPCell .Border = PdfCell.NO_BORDER;
PdfPTable .AddCell(PdfPCell );
Please take a look at the following screen shot:
Based on your code snippet, I assume that you want to separate "Received Rs (in Words):" from "Priceless", but it's not clear to me what you want to happen if there is more than one line, so I have written 3 examples:
Example 1:
table = new PdfPTable(2);
table.setHorizontalAlignment(Element.ALIGN_LEFT);
table.setWidthPercentage(60);
table.setSpacingAfter(20);
cell = new PdfPCell(new Phrase("Received Rs (in Words):"));
cell.setBorder(PdfPCell.LEFT | PdfPCell.TOP | PdfPCell.BOTTOM);
table.addCell(cell);
cell = new PdfPCell(new Phrase("Priceless"));
cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
cell.setBorder(PdfPCell.RIGHT | PdfPCell.TOP | PdfPCell.BOTTOM);
table.addCell(cell);
document.add(table);
In this example, I put "Received Rs (in Words):" and "Priceless" in two different cells, and I align the content of the first cell to the left and the content of the second cell to the right. This creates space between the two Chunks.
Example 2
// same code as above, except for:
table.setWidthPercentage(50);
I decreased the width of the table to show you what happens if some content doesn't fit a cell. As we didn't define any widths for the columns, the two columns will have an equal width, but as "Received Rs (in Words):" needs more space than "Priceless", the text doesn't fit the width of the cell and it is wrapped. We could avoid this, by defining a larger with for the first column when compared to the second column.
Example 3:
table = new PdfPTable(1);
table.setHorizontalAlignment(Element.ALIGN_LEFT);
table.setWidthPercentage(50);
Phrase p = new Phrase();
p.add(new Chunk("Received Rs (In Words):"));
p.add(new Chunk(new VerticalPositionMark()));
p.add(new Chunk("Priceless"));
table.addCell(p);
document.add(table);
This example is very close to what you have, but instead of introducing space characters to create space, I introduce a special chunk: new VerticalPositionMark()). This chunk will separate the two parts of the Phrase by introducing as much space as possible.
If this doesn't answer your question, you were probably looking for the concept known as leading. Leading is the space between the baseline of two lines of text. If that is the case, please read the following Q&As:
Changing text line spacing
Spacing/Leading PdfPCell's elements
Paragraph leading inside table cell
Adding more text to a cell in table in itext
How to maintain indentation if a paragraph takes new line in PdfPCell?
If your question isn't about leading, then maybe you're just looking for the concept known as non-breaking space:
How to use non breaking space in iTextSharp
Generating pdf file using Itext

How to display text in center if use verticalText?

My code
VerticalText vt = new VerticalText(writer.getDirectContent());
vt.setVerticalLayout(marginLeft + squareHeight, 1191.0f - marginTop, squareHeight, 3, 20);
vt.setAlignment(Element.ALIGN_CENTER);
Paragraph p = new Paragraph(imgr.getText(), fontV);
p.setLeading(10);
vt.addText(p);
vt.go();
The result : Text is middle in vertical mode.
I want to display text is center in horizontal mode as below link:
How to solve this problem ?
As documented, left, center and right align has a different meaning in the context of VerticalText. Left is top, center is middle and right is bottom.
With class VerticalText, you always write from right to left. There is currently no way to align the text as shown in the screen shot to the right.
However, you could work around this problem by adding the vertical text in simulation mode first and then calculate the number of lines that have been written.
See for instance the VerticalText1 example from my book. I have adapted the code of that example like this:
BaseFont bf = BaseFont.createFont(
"KozMinPro-Regular", "UniJIS-UCS2-V", BaseFont.NOT_EMBEDDED);
Font font = new Font(bf, 20);
VerticalText vt = new VerticalText(writer.getDirectContent());
vt.setVerticalLayout(390, 570, 540, 12, 30);
vt.addText(new Chunk(MOVIE, font));
vt.go();
System.out.println(vt.getMaxLines());
vt.addText(new Phrase(TEXT1, font));
vt.go();
System.out.println(vt.getMaxLines());
vt.setAlignment(Element.ALIGN_RIGHT);
vt.addText(new Phrase(TEXT2, font));
vt.go();
System.out.println(vt.getMaxLines());
The output of the System.out calls is:
11
4
1
These numbers are the number of lines that are available after each go().
We start with 12 lines as defined in the setVerticalLayout() method.
We add MOVIE and there are 11 lines left. We've defined a leading of 30, which means we've already consumed (12 - 11) x 30pt = 30pt.
Then we add TEXT1 which is distributed over 7 lines, which take 7 * 30pt in width. In total we now have consumed (12 - 4) x 30pt = 240pt.
Finally we add TEXT2 which is distributed over 3 lines. Only 1 line is left. The total horizontal width of all the text is 330pt (we had only 30pt left).
Now that you know this math, you can execute the go() method in simulation mode, calculate the width that was consumed and use that info to add your text for real at the desired position.

Changing text line spacing

I'm creating a PDF document consisting of text only, where all the text is the same point size and font family but each character could potentially be a different color. Everything seems to work fine using the code snippet below, but the default space between the lines is slightly greater than I consider ideal. Is there a way to control this? (FYI, type "ColoredText" in the code below merely contains a string and its color. Also, the reason I am treating the newline character separately is that for some reason it doesn't cause a newline if it's in a Chunk.)
Thanks,
Ray
List<byte[]> pdfFilesAsBytes = new List<byte[]>();
iTextSharp.text.Document document = new iTextSharp.text.Document();
MemoryStream memStream = new MemoryStream();
iTextSharp.text.pdf.PdfWriter.GetInstance(document, memStream);
document.SetPageSize(isLandscape ? iTextSharp.text.PageSize.LETTER.Rotate() : iTextSharp.text.PageSize.LETTER);
document.Open();
foreach (ColoredText coloredText in coloredTextList)
{
Font font = new Font(Font.FontFamily.COURIER, pointSize, Font.NORMAL, coloredText.Color);
if (coloredText.Text == "\n")
document.Add(new Paragraph("", font));
else
document.Add(new Chunk(coloredText.Text, font));
}
document.Close();
pdfFilesAsBytes.Add(memStream.ToArray());
According to the PDF specification, the distance between the baseline of two lines is called the leading. In iText, the default leading is 1.5 times the size of the font. For instance: the default font size is 12 pt, hence the default leading is 18.
You can change the leading of a Paragraph by using one of the other constructors. See for instance: public Paragraph(float leading, String string, Font font)
You can also change the leading using one of the methods that sets the leading:
paragraph.SetLeading(fixed, multiplied);
The first parameter is the fixed leading: if you want a leading of 15 no matter which font size is used, you can choose fixed = 15 and multiplied = 0.
The second parameter is a factor: for instance if you want the leading to be twice the font size, you can choose fixed = 0 and multiplied = 2. In this case, the leading for a paragraph with font size 12 will be 24, for a font size 10, it will be 20, and son on.
You can also combine fixed and multiplied leading.
private static Paragraph addSpace(int size = 1)
{
Font LineBreak = FontFactory.GetFont("Arial", size);
Paragraph paragraph = new Paragraph("\n\n", LineBreak);
return paragraph;
}

Add rectangle as inline-element with iText

How do I add a rectangle (or other graphical elements) as inline-elements to an iText PDF?
Example code of what I'm trying to achieve:
foreach (Row r in entrylist)
{
p = new Paragraph();
p.IndentationLeft = 10;
p.SpacingBefore = 10;
p.SpacingAfter = 10;
p.Add(new Rectangle(0, 0, 10, 10)); <<<<<<<<< THAT ONE FAILS
p.Add(new Paragraph(r.GetString("caption"), tahoma12b));
p.Add(new Paragraph(r.GetString("description"), tahoma12));
((Paragraph)p[1]).IndentationLeft = 10;
doc.Add(p);
}
It's something like a column of text-blocks, of which each of them have (only a printed) checkbox.
I've tried various things with DirectContent, but it requires me to provide absolute X and Y values. Which I simply don't have. The elements should be printed at the current position, wherever that may be.
Any clues?
You need a Chunk for which you've defined a generic tag. For instance, in this example listing a number of movies, a snippet of pellicule is drawn around the year a movie was produced and an ellipse was drawn in the background of the link to IMDB.
If you look at the MovieYears example, you'll find out how to use the PdfPageEvent interface and its onGenericTag() method. You're right that you can't add a Rectangle to a Paragraph (IMHO that wouldn't make much sense). As you indicate, you need to draw the rectangle to the direct content, and you get the coordinates of a Chunk by using the setGenericTag() method. As soon as the Chunk is drawn on the page, its coordinates will be passed to the onGenericTag() method.