Get height of text in PDF AcroField - c#

Is there any technique to calculate the height of text in AcroField?
In other words, I have a template PDF with a body section that I want to paste my long text into and I want to get the height of the text. If it overflows, insert a new page for rest of the text.

This will give height and width:
Vector curBaseline = renderInfo.GetBaseline().GetStartPoint();
Vector topRight = renderInfo.GetAscentLine().GetEndPoint();
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(
curBaseline[Vector.I1], curBaseline[Vector.I2],
topRight[Vector.I1], topRight[Vector.I2]
);
Single curFontSize = rect.Height;

Just set your field to a font size of zero. This will automatically size the font so that the given text will fit into your field... within certain limits. I don't think it'll shrink below 6 points.
Another alternative would be to use a ColumnText and call myColText.go(true). This will "simulate" layout, letting you know what goes where without actually drawing anything to the PDF. Just whip up a columnText with the same dimensions, font&font-size as your field, and your results should be the same.
In fact, I believe iText's text field rendering code uses ColumnText internally. Yep, have a look at the source for TextField.getAppearance().
Note that the bounding box of your field isn't going to match the box the text is laid out into... you have to account for borer style & thickness. That's why I suggest you look at the source.

Related

iText7 MoveText and rectangle object

When I use the pdfCanvas object I have the MoveText method where I can set the x and y coordinate but I don't see that in the Paragraph object? Second thing is why do I need the rectangle object I am not adding any Rectangle to the pdf just Text. Where I want the text to take the full width of the page. Can I get the size of the font and text and then calculate the centeredWidth and centeredHeight if I only have MoveText method in pdfCanvas?
for (int i = 1; i <= numberOfPages; i++)
{
PdfPage pdfPage = pdfDocument.GetPage(i);
iText.Kernel.Geom.Rectangle pageSizeWithRotation = pdfPage.GetPageSizeWithRotation();
float n2 = 15F;
float n3 = pageSizeWithRotation.GetHeight() - 10F;
float frontSize = 6.25f;
PdfCanvas pdfCanvas = new PdfCanvas(pdfPage);
iText.Kernel.Geom.Rectangle rectangle = new iText.Kernel.Geom.Rectangle(100, 100, 100, 100);
Canvas canvas = new Canvas(pdfCanvas, rectangle);
PdfFont font = PdfFontFactory.CreateFont("C:\\Windows\\Fonts\\ARIALN.TTF");
Paragraph p = new Paragraph()
.Add(disclaimerText)
.SetFont(font)
.SetFontSize(frontSize)
.SetTextAlignment(TextAlignment.CENTER);
canvas.Add(p);
canvas.Close();
//pdfCanvas.BeginText()
// .SetFillColorRgb(0, 0, 0)
// .SetFontAndSize(PdfFontFactory.CreateFont("C:\\Windows\\Fonts\\ARIALN.TTF"), frontSize)
// .MoveText(n2, n3)
// .ShowText(disclaimerText)
// .EndText();
}
First of all, please be aware that you are using different parts of the iText API with PdfCanvas on one side and Canvas on the other side:
PdfCanvas is merely a thin wrapper for the instructions written into the PDF. When using this class, you have to determine yourself where you want to start text lines, where to break the lines, how much space to add between characters, words, and lines, and so on.
Canvas (and Document) on the other hand features its own layout engine, you only initialize it with the PdfCanvas to work on and the coordinate ranges in which you want it to operate, and then you feed it paragraphs, tables, etc. which Canvas arranges properly.
Thus, you essentially have the choice, do you foremost want to arrange everything yourself, or do you foremost want to leave that task to iText.
That being said, let's look at your questions:
When I use the pdfCanvas object I have the MoveText method where I can set the x and y coordinate but I don't see that in the Paragraph object?
Paragraphs mostly are designed for automatic layout by Canvas and Document. Nonetheless, you can statically arrange them at given coordinates using the SetFixedPosition overloads.
Second thing is why do I need the rectangle object I am not adding any Rectangle to the pdf just Text.
You need the rectangle to tell Canvas where on the (theoretically endless) PdfCanvas coordinate plane it shall arrange the objects you give it.
Where I want the text to take the full width of the page.
Then use the full crop box of that page, assuming you mean the full visible width of the page on screen or the final printed product. You can get it using the PdfPage method GetCropBox.
If you are not sure which "full widths of the page" there are, have a look at this answer.
Can I get the size of the font and text and then calculate the centeredWidth and centeredHeight if I only have MoveText method in pdfCanvas?
You don't get the size of the font, you set it (using SetFontAndSize as you show in your code). You also set the font. And the PdfFont object you set has nice GetWidth overloads to determine the widths of some text drawn using that font. That in combination with the crop box mentioned above and trivial math allows you to calculate everything you need for simple text drawing.

Get number of rows of a text

I have a string that can be anything and I have a text object in my scene which has a set width and a changeable height.
Is there a built-in function that counts how many rows my string would have in that text object so that I can adjust the height of it? I want to do this because I need a background only at the text and not anywhere else.
I want to do this because I need a background only at the text and not anywhere else.
It appears to me that this should be able to solve your problem:
In order to make a Rect Transform with a Text component on it fit the text content, add a Content Size Fitter component to the same Game Object which has the Text component. Then set both the Horizontal Fit and Vertical Fit dropdowns to the Preferred setting.
In your case you want to control the Horizontal but not the vertical, so try set the Vertical setting to "Preferred".
If this does not work directly on your text component you may want to make the text component a child of the grey panel box and then add the contentfitter to it as well.
Source: https://docs.unity3d.com/Manual/HOWTO-UIFitContentSize.html
Disclaimer: I didn't test this Component based attempt, but I believe it may be the solution or lead you closer to one.
While Doh09's answer is certainly accurrate, you can also query the UI.Text.preferredHeight property, asking the Text object how tall the text is and using that value to change the size of your background object yourself.
Of course, both answers assume you are using the New UI text and not TextMesh or OnGUI. If you are not using the New UI, then I suggest changing to using the New UI.
You can see an example usage of this in my own project here where I compute the text's desired width and height and modify the RectTransform until the object's preferred size is within a layout-preferred ratio. Here's one of the final sections (with some alterations to make it understandable):
Text t = <some Text object>
float height = t.preferredHeight;
float width = t.preferredWidth;
((RectTransform)tooltipGO.transform).SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, (width / 4) + 8);
((RectTransform)tooltipGO.transform).SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, (height / 4) + 7.5f);
The divide-by-four and offsets to account for relative scaling between the text and the background and some edge padding.

How to tweak the vertical position of text in a cell?

I have a problem with the vertical alignment in a table. The text is too close to the bottom border:
My code looks like this:
nested = new PdfPTable(3);
nested.DefaultCell.VerticalAlignment = Element.ALIGN_MIDDLE;
nested.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
nested.WidthPercentage = 100;
nested.AddCell(new Phrase("blablabla"));
nested.AddCell(new Phrase("blablabla"));
nested.DefaultCell.HorizontalAlignment = Element.ALIGN_RIGHT;
nested.AddCell(new Phrase("Stand: " +
pdfdoc.Add(nested);
Adding or removing the line DefaultCell.VerticalAlignment = Element.ALIGN_MIDDLE; doesn't have any effect.
You are creating PdfCell object with only one line of text. The height of the cell will be determined based on that line of text. The text will be aligned in the middle automatically. That explains why adding or removing DefaultCell.VerticalAlignment = Element.ALIGN_MIDDLE; has no effect: as far as iText is concerned, the text is already aligned in the middle.
You claim that this isn't true because it's your perception that the base line of the text is too close to the bottom. I understand that claim, but if your read my answer to the question How does a PdfPCell's height relate to the font size? you should understand which factors create that perception:
The leading: the default font size is 12 pt; the default leading is 18 pt. A leading of 18 pt is kind of high and results in extra space above the base line. If you reduce the leading, you'll see that there's less space at the top.
Different fonts have different ascender and descender values; the way you add the cells, iText won't take those values into account.
My suggestion: tell iText to use the ascender and descender of the font you're using:
nested.DefaultCell.UseAscender = true;
nested.DefaultCell.UseDescender = true;
You'll notice that the position of the text will already be much better. If it's not better, you may want to add some padding. All of this is, of course, explained in the official documentation where you'll find an example called Spacing.cs. Try this example and you'll see how the position of the content changes by tweaking values such as UseAscender, UseDescender, Padding, and so on.

Determining height of a block of text in a console application

I'm trying to determine the size of the textframe that will be needed for a block of text. This is to then be exported for an InDesign script to create the page. All in a console application.
I've tried to create a WPF TextBlock and assign the Text and a Width, but the Height and ActualHeight is NaN.
How can I determine the size of a textframe that will be needed for some text? Is using a WPF / Winforms textblock the best solution (to try and take advantage of existing code), or is there some other, better workflow?
There are two classes in C# that are used to draw text. TextRenderer and Graphics.
TextRenderer uses GDI to render the text, whereas Graphics uses GDI+. The two use a slightly different method for laying out text.
You can make use of Graphics.MeasureString or TextRenderer.MeasureText
Example
using( Graphics g = Graphics.FromHwnd(IntPtr.Zero) )
{
SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}
For your case I would suggest using TextRenderer. Text wrapping example -
var size = TextRenderer.MeasureText(text, font, new Size(width, height), TextFormatFlags.WordBreak);
The third argument is size of the drawing rectangle. You can pass height as 0 if you don't know it.

itextsharp measure chunk width / height

I am trying to do some precise alignment with iTextSharp, but I keep falling short as I can't figure out a way to get a width / height value for a chunk or paragraph. If I create a paragraph that is a certain font and size and text, then its dimensions should be known, right?
I know that the default left/right/center alignments will do the trick for me mostly, but I have scenarios where knowing the dimensions will be most useful. Any ideas?
You can get a chunk's width using GetWidthPoint() and the height of a chunk is generally the font's size unless you're using only lowercase letters. If so then you can manually measure characters using BaseFont.GetCharBBox().
Paragraphs are flowable items, however, and they depend on the context that they are written into so measuring them is harder. (Chunks don't automatically wrap but Paragraphs do.) The best way to measure a paragraph is to write it to a PdfCell and then measure the PdfCell. You don't have to actually add the PdfCell to the document. The link below explains it a little more.
http://itext-general.2136553.n4.nabble.com/Linecount-td2146114.html
Use below code for exact size
Font font = ...;
BaseFont baseFont = font.BaseFont;
float width = baseFont.GetWidthPoint(text, fontSize);
float height = baseFont.GetAscentPoint(text, fontSize) - baseFont.GetDescentPoint(text, fontSize);

Categories