iText Vertical Alignment in Text inside a Canvas isn't working - vb.net

I'm trying to set my text which is inside a canvas to get vertically aligned with VerticalAlignment.BOTTOM property value, but whatever I put doesn't change the visual result.
retangulo = New iText.Kernel.Geom.Rectangle(122, AlturaPag - 208, 235, 27)
PdfCanvas = New iText.Kernel.Pdf.Canvas.PdfCanvas(page).SetLineWidth(1).Rectangle(retangulo).Stroke()
canvas = New iText.Layout.Canvas(PdfCanvas, retangulo)
texto = (New iText.Layout.Element.Text(Npagador).SetFontSize(11).SetBold)
' VerticalAlingment = BOTTOM \/
paragrafo = (New iText.Layout.Element.Paragraph().Add(texto).SetTextAlignment(TextAlignment.LEFT).SetVerticalAlignment(VerticalAlignment.BOTTOM))
canvas.Add(paragrafo)

You are trying to align the contents of the paragraph to the bottom of the paragraph itself, and the paragraph when laying itself out simply uses the minimal necessary height, so whatever alignment (bottom or top) you set, the result it just the same simply because paragraph packs itself to the minimal height.
To make sure setVerticalAlignment has an effect, you need to give the paragraph more vertical space by setting its height. Here is an example where I set paragraph height to match the height of the canvas you add it to, since it's the only element in the canvas. I also set the margins of the paragraph to zero so that you don't get additional spacing around the text.
The code is in Java but you will be able to convert it back to VB.NET as easily as I converted your code to Java:
Paragraph p = new Paragraph().add("Test").setTextAlignment(TextAlignment.LEFT)
.setVerticalAlignment(VerticalAlignment.BOTTOM).setHeight(retangulo.getHeight());
p.setMargin(0);

Related

Is there a way to set the dimensions of a paragraph in itext7?

Trying to set the height along with setting the rotation on a Paragraph object results in the following error:
ERROR c.i.layout.renderer.BlockRenderer - Rotation was not correctly processed for ParagraphRenderer
Also, the height is sent to infinity resulting in an apparently empty page which I'm not sure if it's the expected behavior or not.
If I don't set the height, the text shows up rotated (which is what I want). But my task is to place the text at certain coordinates with certain dimensions and rotation. The placement is fine, but not being able to set the height results in assigning the rotation points to the wrong values and in turn displacing the final position of the text.
Paragraph paragraph = new Paragraph(text);
paragraph.setHeight(height);
paragraph.setMargins(0, 0, 0, 0);
paragraph.setProperty(ROTATION_POINT_X, x);
paragraph.setProperty(ROTATION_POINT_Y, y);
paragraph.setProperty(ROTATION_ANGLE, asFloat(toRadians(rotation))));
document.add(paragraph);
Setting the margins to 0 doesn't seem to have any influence either. The text looks to keep some sort of margin anyway.
So is there a way to control what the dimensions of the object displayed are? I could also settle for a way to make the rotation pivot from the center of the object.
You should set both width and height at the same time for rotated objects.
Here is an example code:
Paragraph paragraph = new Paragraph("Hello world");
paragraph.setWidth(200);
paragraph.setHeight(20);
paragraph.setBackgroundColor(ColorConstants.RED);
paragraph.setMargins(0, 0, 0, 100);
paragraph.setProperty(ROTATION_POINT_X, paragraph.getWidth().getValue() / 2);
paragraph.setProperty(ROTATION_POINT_Y, paragraph.getHeight().getValue() / 2);
paragraph.setRotationAngle(Math.PI / 180 * 45);
document.add(paragraph);
Visual result:

iText - PDFAppearence issue

We're using iText to put a text inside a signature placeholder in a PDF. We use a code snippet similar to this to define the Signature Appearence
PdfStamper stp = PdfStamper.createSignature(inputReader, os, '\0', tempFile2, true);
sap = stp.getSignatureAppearance();
sap.setVisibleSignature(placeholder);
sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
sap.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
Calendar cal = Calendar.getInstance();
sap.setSignDate(cal);
sap.setLayer2Text(text+"\n"+cal.getTime().toString());
sap.setReason(text+"\n"+cal.getTime().toString()); `
Everything works fine, but the signature text does not fill all the signature placeholder area as expected by us, but the area filled seems to have an height that is approximately the 70% of the available space.
As a result, sometimes especially if the length of the signature text is quite big, the signature text does not fit in the placeholder and the text is striped away.
Example of filled Signature:
I looked into the PdfSignatureAppearence class and I found this code snippet in the getApperance() method that is responsible of this behaviour and is invoked when
sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
is being called
else {
dataRect = new Rectangle(
MARGIN,
MARGIN,
rect.getWidth() - MARGIN,
rect.getHeight() * (1 - TOP_SECTION) - MARGIN);
}
I don't get the reason for that, because I expect that the text could use all the available placeholder height, with the proper margin.
Is there any way to bypass this behaviour?
We are using iText 5.4.2, but also newer version contains same code snippet so I expect that the behaviour will be same.
As #JJ. already commented,
TOP_SECTION is connected with acro6layers rendering and the code [determining the datarect in pure DESCRIPTION mode] does not take into account the value of the acro6layer flag.
Unless one wants to fix this in the iText 5 code itself, the easiest way to make one's description use the whole signature space is to construct the layer 2 appearance oneself.
To do so one merely has to retrieve a PdfTemplate from PdfSignatureAppearance.getLayer(2) and fill it as desired after one has called PdfSignatureAppearance.setVisibleSignature. The PdfSignatureAppearance remembers that you already have retrieved the layer 2 and doesn't change it anymore.
For the case at hand we essentially copy the PdfSignatureAppearance.getAppearance code for generating layer 2 in pure DESCRIPTION mode, merely correcting the code determining the datarect:
PdfSignatureAppearance appearance = ...;
[...]
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
PdfTemplate layer2 = appearance.getLayer(2);
String text = "We're using iText to put a text inside a signature placeholder in a PDF. "
+ "We use a code snippet similar to this to define the Signature Appearence.\n"
+ "Everything works fine, but the signature text does not fill all the signature "
+ "placeholder area as expected by us, but the area filled seems to have an height "
+ "that is approximately the 70% of the available space.\n"
+ "As a result, sometimes especially if the length of the signature text is quite "
+ "big, the signature text does not fit in the placeholder and the text is striped "
+ "away.";
Font font = new Font();
float size = font.getSize();
final float MARGIN = 2;
Rectangle dataRect = new Rectangle(
MARGIN,
MARGIN,
appearance.getRect().getWidth() - MARGIN,
appearance.getRect().getHeight() - MARGIN);
if (size <= 0) {
Rectangle sr = new Rectangle(dataRect.getWidth(), dataRect.getHeight());
size = ColumnText.fitText(font, text, sr, 12, appearance.getRunDirection());
}
ColumnText ct = new ColumnText(layer2);
ct.setRunDirection(appearance.getRunDirection());
ct.setSimpleColumn(new Phrase(text, font), dataRect.getLeft(), dataRect.getBottom(), dataRect.getRight(), dataRect.getTop(), size, Element.ALIGN_LEFT);
ct.go();
(CreateSignature.java test signWithCustomLayer2)
(As description text I used some paragraphs from the question body.)
The result:
By adapting the MARGIN value in the code above, one can even use more are. As that can result in the text touching the border, though, that might not be really beautiful.
As an aside:
if the length of the signature text is quite big, the signature text does not fit in the placeholder and the text is striped away.
If you initialize the size variable above with a non-positive value, the code in the if (size <= 0) block will calculate a font size which allows all of the text to fit into the signature rectangle. This does happen in the code above as new Font() returns a font with a size of UNDEFINED which is a constant -1.

Text Formatting To Avoid Overwritting

I already saw this question but it doesn’t help me.
The problem is that I can write the text to the PDF file, but if I do that with a new gfx.DrawString it put the second text on the first...
like this....
Here is my code I used to set a new line:
gfx.DrawString(lbname.Text + " " + lbnamei.Text, font, XBrushes.Black, new XRect(0, 0, page.Width.Point, page.Height.Point), XStringFormats.TopLeft);
gfx.DrawString(lbvorname.Text + " " + lbvornamei.Text, font, XBrushes.Black, new XRect(0, 0, page.Width.Point, page.Height.Point), XStringFormats.TopLeft);
I think it has something to do with the numbers in the first argument (new XRect(0, 0,) but it is unclear how to set them.
I can't remember which parameter does which, but this will help you discover for yourself:
Set one of the numbers to 20 on one of the pieces of text; observe the effect. Then change it back and change a different number; observe the effect.
An XRect has the four parameters x, y, width, height. x is the position from the left, y is the position from the top.
Width and height have no effect as long as XStringFormats.TopLeft is used. Therefore it is enough with the code shown above to increment y to draw text in a new line.
Width must be set to have text that is right-aligned or horizontally centered.
Height must be set to have text that is bottom-aligned or vertically centered.

How to determine size of text drawn in rectangle

I am outputting text on a printed page and using drawstring to draw the text in a rectangle so that it will word wrap using a call such as:
ev.Graphics.DrawString(textToOutput, printFont, myBrush, New RectangleF(leftMargin, yPosition, pagewidth - leftMargin - rightmargin, 400))
This works fine. What I am trying to determine is what the Y position would be after the drawscreen call (in other words, what was the height of the text after it was wrapped in the rectangle). I am trying to print variable length strings from a database and they will frequently exceed the page width. I need to know where the vertical start of the next paragraph will be.
You can use Graphics.MeasureString and perhaps this overload of it. Part of the example from MSDN:
Dim stringSize As New SizeF
stringSize = e.Graphics.MeasureString(measureString, stringFont, stringWidth)
Your calculated height would be stored in SizeF.Height.

Is there a way to resize an MdiTab to fit your newly-updated text? (Infragistics)

I am resetting the text for an MdiTab in an UltraWinTabbedMdi. I reset it to be bold and longer, but the tab does not resize so the text is truncated. Right now, I'm just resetting the size of the tab to some magic number that I've found looks decent on my computer, but I don't know if it will work elsewhere. I would like to be able to get the dimensions of the new text and add the same size to that every time or call some auto-resize method.
Is there a way to do this?
You could use the MeasureString of the Graphics class.
// Set up string.
string measureString = "YourText";
// The font name and size used to draw the string (from your MdiTab)
Font stringFont = new Font("Arial", 16);
// Measure string.
SizeF stringSize = new SizeF();
stringSize = this.Graphics.MeasureString(measureString, stringFont);
// now you have a stringSize.Width and stringSize.Height to use