itextsharp measure chunk width / height - c#

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);

Related

How to obtain DPI equivalent of an adjustable column with no text in OpenXML

I would like to ask what units does column.width return when using Openxml? (IS it in EMU, metres, cm or dpi and how do i get its DPI equivalent?
From SpreadsheetOpenXmlFromScratch:
Note that the width of the digits depends on the font and the font size used. I'll be using the MeasureString() function of the Graphics class to measure pixel width.
Everything Vincent does is based on the font type and size. You will have to retrieve the font type and font size to run through the calculations.
EDIT: pp 40-50
No, it is using the font measurements, not the column text. Another excerpt:
Note that the width of the digits depends on the font and the font size used. I'll be using the MeasureString() function of the Graphics class to measure pixel width.
System.Drawing.Font drawfont = new System.Drawing.Font("Calibri", 11, FontStyle.Regular);
// I just need a Graphics object. Any reasonable bitmap size will do.
Graphics g = Graphics.FromImage(new Bitmap(256, 256));
Dim drawfont As New System.Drawing.Font("Calibri", 11, FontStyle.Regular)
' I just need a Graphics object. Any reasonable bitmap size will do.
Dim g As Graphics = Graphics.FromImage(New Bitmap(256, 256))
The font used should be the same as that used in your stylesheet. Otherwise you would be measuring for one font or font size, but using another font or font size to render your actual text in the Excel cell. I know it's obvious, but it's important to state here.
Specifically, it should be the font used in the Normal style. That word is capitalised for a reason. It refers to the cell style named Normal (together with "Good", "Bad" and "Neutral"). Get your friendly neighbourhood Excel geek to help you find the cell style option in Excel.
Some of his other methods do require text when he actually measures the width of a zero flanked by two underscores, then subtracts the width of the underscores to get a more accurate width, but this just requires the font name and style.
Now the MeasureString() function has a tiny problem. This is from the official documentation:
The MeasureString method is designed for use with individual strings and includes a small amount of extra space before and after the string to allow for overhanging glyphs.
What this means is that the following code will not exactly give you the pixel width of "0":
fWidthOfZero = (double)g.MeasureString("0", drawfont).Width;
fWidthOfZero = Convert.ToDouble(g.MeasureString("0", drawfont).Width)
Give it a try.

C# calculate the height of a string in with the given width

Im trying to write text in C# so that it spans the required width (approximately).
To write text you need to specify the height. So I need to know what height would make it write to the desired length.
Font myFont = new Font(FontFamily.GenericSansSerif, unknown);
gc.DrawString(LabelText, myFont, gBrush, 0, 0);
Ive found the following, but it requires FONT, which requires height. Which defeats the whole point?
gc.MeasureString(LabelText, new Font(FontFamily.GenericSansSerif, 12), length);
How would I determine the required height to make for example "I am a String" stretch 50px.
There is an example on the site switchonthecode (note - archived version). They provide a method that takes a minimum and maximum font size along with the size of your area. It tries the minimum size and from there determines the ratio of the font and then determines the best size for you.

Strange behavior of graphics.MeasureString at different resolutions

I have noticed strange behavior of Graphics.MeasureString at different resolutions.
For the default resolution (96x96) there is a linear relationship across the different font sizes I tested.
However, if I raise it to 512 x 512, the linear relationship disappears and something really strange happens when using measure string. (See 4 plots below)
If I leave the resolution at the default size for a graphics object, and measure the font size, here is the relationship between font size and the width of a string:
Graphics object, Default Resolution (96):
Font size (X-Axis), WIDTH of a particular string (Y-Axis)
Font size (X-Axis), HEIGHT of a particular string (Y-Axis)
However, if I change the resolution
Graphics object, 512 resolution:
Font size (X-Axis), WIDTH of a particular string (Y-Axis)
Font size (X-Axis), HEIGHT of a particular string (Y-Axis)
Anyone know why this might be happening?
Thanks you.
It should noted that I am using .NET 4 (Full Profile)
Code used to generate graphs (Change resolution for each type):
string str = "6 CN-3 Tie EomgVeo405- 2ss>era09rni IBne 20iopv Atdrsn - Ng72";
SizeF sizef = new SizeF(855, 14.000001f);
StringFormat stringFormat = new StringFormat()
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Near,
Trimming = StringTrimming.None,
FormatFlags = StringFormatFlags.NoClip,
};
Bitmap b = new Bitmap(901, 401);
//b.SetResolution(512, 512);
Graphics g = Graphics.FromImage(b);
for (float x = origFont.Size; x >= 0.5; x -= 0.1f)
{
var data = g.MeasureString(str, new Font("Microsoft Sans Serif", x), sizef, stringFormat);
Console.WriteLine(x + "\t" + data.Width + "\t" + data.Height);
}
This answer is a guess, but the evidence fits it perfectly.
What you're seeing is the string being wrapped onto two lines.
Let's assume the following:
The width of the text is linearly proportional to the fontsize
The height of the text is linearly proportional to the fontsize
This fits the start of your 512-resolution graph, everything increases linearly.
At some point, the width is sharply reduced by a certain amount, and at the same time the height doubles.
This means that a word was moved onto line 2, which doubled the height (2 lines vs. 1 before), and the string got a certain amount less wide since the last word on the line is now on the start of line 2.
From there on, the width slowly increases again as the part of the string still on line 1 linearly gets wider as the font-size increases. At the same time the height increases linearly, but now at double the rate as before the break, since 2 lines now get higher, vs. 1 before.
At some point, again, the last word on line 1 breaks the maximum width and is moved down on line 2, before the word that was previously alone there, and at that point, the width is again sharply reduced by a certain amount.
If you were to continue your graph, I predict that the width will continue its current pattern. The exact amount it dips down each time is proportional to the width of the word being moved. At the same time, at some point the 2nd line will need to be broken, in which case you get a 3x height and the height will then increase at 3x the pace, and so on.
I believe this might be happening because of the hinting/grid fitting algorithms in GDI+. Font sizes in your tests are extremely small in terms of glyph legibility, and, because of that, the rendering engine tries to apply special transformations to each glyph to make it clearer. These transformations depend greatly on the target DPI.
It is also worth mentioning that major increase of the font size will lead to a more 'linear' dependency.
This article explains these mechanisms in more details with some examples.
Meanwhile, you can try to modify the Graphics.TextRenderingHint property and/or try TextRenderer instead of Graphics.DrawString if that will help you with your issue.

Get height of text in PDF AcroField

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.

WPF definition of FontSize

I know that in WPF, FontSize = 1/96 of an inch (same as 1 pixel I think). Is the FontSize dimension the height, the width, or diagonal size of a character? I would guess it's the font height, but the Microsoft documentation doesn't really indicate what it is.
Also, is there an easy way to get the height and width of a font size?
Answer:
So it looks like the FontSize is the height, and the width can only be determined (without knowing the actual character) on monospaced fonts since proportional fonts have varying widths.
They are referring to Font Size as used in Typefaces for Typography.
You can read about it here: Wikipedia: Typeface
The size of typefaces and fonts is traditionally measured in points;2 point has been defined differently at different times, but now the most popular is the Desktop Publishing point of 1⁄72 in (0.0139 in/0.35 mm). When specified in typographic sizes (points, kyus), the height of an em-square, an invisible box which is typically a bit larger than the distance from the tallest ascender to the lowest descender, is scaled to equal the specified size.[3] For example, when setting Helvetica at 12 point, the em square defined in the Helvetica font is scaled to 12 points or 1⁄6 in (0.17 in/4.3 mm). Yet no particular element of 12-point Helvetica need measure exactly 12 points.
A note...72 as stated in this Wikipedia article is what WinForms used. WPF switched to 96.
As for the second part of your question, I found this resource from an MSDN Link:
FormattedText formattedText = new FormattedText(
textBox1.Text.Substring(0, 1),
CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(textBox1.FontFamily.ToString()),
textBox1.FontSize,
Brushes.Black
);
... formattedText.WidthIncludingTrailingWhitespace;
... formattedText.Height;

Categories