Determining height of a block of text in a console application - c#

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.

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.

Resizing bitmap to draw string

I want to draw string in a Bitmap like this:
Font myfont=new Font("TimesNewRoman",18)
Bitmap bmpBitmap =new Bitmap(200,100);
Graphics g=Graphics.FromImage(bmpBitmap);
g.DrawString("SampleText",myfont,Brushes.Black);
How do I determine the size of bitmap?
Use the following function to measure the size of a string with respect to a certain Font.
SizeF Graphics.MeasureString(string text, Font font)
Also, ensure the TextRenderingHint for the Graphics is set to AntiAlias. This makes a world of difference when it comes to the readability of the text.
If you want to measure a string before you create your Bitmap, use the solution presented over here: https://stackoverflow.com/a/1003503/1828879
Have you tried using bmpBitmap.Size to get both Height and Width, or
bmpBitmap.Height and bmpBitmap.Width to get one or the other?

How to Adjust the Text Size according to image size while Drawing String on an Image in C#

I'm using the Drawstring method of the Graphics Class to Draw a Text on an Image.The Font is Specified before drawing.
G.DrawString(mytext, font, brush, 0, 0)
The Problem arises when the same text is drawn on an image with smaller size.The Text drawn appears to be larger.I'm looking for a solution to alter the font size according to the image size so that the text don't appear larger or smaller when drawn on images of different sizes.
I'm attaching the images with different sizes with the text of same font size drawn on it.
http://i.stack.imgur.com/ZShUI.jpg
http://i.stack.imgur.com/GUfbM.jpg
I can't directly post the image because I'm not allowed.
You would get most precise scaling by drawing on separate image and then slapping that image onto original one. You'd do that as follows:
Create in-memory Bitmap with enough space
Draw text on that bitmap in your default font
Draw image containing the text onto original image by scaling it to size you need
Code:
Bitmap textBmp = new Bitmap(100, 100);
Graphics textBmpG = Graphics.FromImage(textBmp);
textBmpG .DrawString("test 1", new Font(FontFamily.GenericSansSerif, 16), Brushes.Red, new PointF(0, 0));
Graphics origImgG = Graphics.FromImage(originalImg);
origImgG.DrawImage(textBmpG, new Rectangle(50, 50, 50, 50), new Rectangle(0, 0, 100, 100), GraphicsUnit.Pixel);
Take notice of last line and Rectangle parameters. Use them to scale your text bitmap onto original image. Alternatively, you can also choose Graphics.MeasureString method to determine how wide your text would be and make attempts until you get best one you can.
Use Graphics.MeasureString() to measure how big your string would be on the image
Decrease/increase font step by step accordingly
As you requested in comment I'll give you more detailed suggestion here. Say your original image width is WI1, and width of text on it using Graphics.MeasureString is WT1. If you resize your image to width WI2, then your perfect text width would be WT2 = WT1 * WI2 / WI1. Using DrawText method you may not be able to get this exact width because when you increase font by 1 it may jump over that value. So you have to make several attempts and find best. Pick a size of font, if resulting text width is smaller (measure with MeasureString), increase it until it becomes bigger than target and you've got about closest match. Same thing goes if it's too big. Decrease font step by step.
This is quick and dirty as you see, because you have many draws, but I can't think of better solution, unless you're using monospaced fonts.
Difference between those solutions would be that in first you can get text to fit EXACT size you need, but you probably would loose some font readability due to scaling. Second solution would give good readability, but you can't get pixel perfect size of text.
In my opinion you have two ways:
Draw text on original image and then resize resulting image (so, even text included in it)
Scale font size by a factor newImageWidth/originalImageWidth.
It's not perfect because you could have some problem with text height (if new image is not just scaled but with different aspect ratio), but it's an idea

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.

How do I convert a Graphics object to a Bitmap object, inside PrintPage event?

This is the high level problem I'm trying to solve...
I have a 3rd party plotting/graphing (IoComp Plot), and I want to embed a high quality (at least 600 dpi) bitmap of the Plot control in reports created by another 3rd party report package (Combit List & Label).
This is the approach that seems most promising so far...
---Edit---:
After trying many other approachs, the only one that I think I can make work is to create a hidden instance of the Plot control, with everything scaled up to printer size (approx 5 times screen size). That includes width and height, font sizes, line widths - every visible component of the control. Yuck!
------
I can get a Graphics object of the proper resolution from the plot control's PrintPage event, but converting it to a Bitmap so the report package will be happy is proving to be the major stumbling block. Several hours of searching has led to other people who asked the same question, but no viable answers.
The only promising lead I've found suggested using one of the Bitmap constructors, which takes a Graphics instance as a parameter.
However, it's not working for me. It creates Bitmap, but with no content from the Plot control - it is a pure black image.
Here's my code (edited to show drawing of red line to Graphics object):
void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
{
// Draw a red line on the Graphics object. When printed, this
// line is shown as part of the normal Plot graphics.
Pen myPen;
myPen = new Pen(Color.Red);
e.Graphics.DrawLine(myPen, 0, 0, 200, 200);
myPen.Dispose();
// Create a bitmap from the Graphics object
Bitmap bm = new Bitmap(1000, 1000, e.Graphics);
// Save to disk
// DOES NOT WORK - CREATES FILE THAT IS PURE BLACK (VIEWED
// WITH "PAINT" PROGRAM)
bm.Save(#"C:\Bicw_Dev\Bic.Net\FrontEnd\GraphicsToBmp.bmp", ImageFormat.Bmp);
bm.Dispose();
}
Can anyone suggest why this doesn't work? Is this even a valid approach?
Also, please note:
As far as I can determine (and I've spent quite a bit of time looking) there is no way to get a high resolution, print quality Bitmap from the Plot control directly!
I stress this because several others who asked the question got code samples in response that solved the opposite problem - converting a Bitmap to a Graphics.
I need to convert a Graphics object to a Bitmap object.
And if anyone can suggest an alternate approach that allows me to get a print quality image of my plots into my reports, please feel free. (For example, I can get a low quality (72 bpi) Bitmap from the Plot control, and have considered trying to stretch it - but I've never seen that approach work well in other applications).
Thanks,
-Tom Bushell
Edit in response to comment:
As an experiment, I added the following:
Pen myPen;
myPen = new Pen(Color.Red);
e.Graphics.DrawLine(myPen, 0, 0, 200, 200);
myPen.Dispose();
This caused a red line to be drawn over the plot graphics when I printed my plot. But it had no effect on the Bitmap - it's still pure black.
However, it's not working for me. It
creates Bitmap, but with no content
from the Plot control - it is a pure
black image.
Well you never do paint to the graphics, what do you expect?
You are suppose to do the actual drawing for the output in that event.
The constructor you're using does not copy any graphics, only sets the resolution equal to the graphics resolution. See msdn. As Leppie points out, you have to actually draw something to the bitmap. I suggest getting another graphics object for the item you just created.
Graphics g = Graphics.FromImage(bmp);
//Make the background white
g.FillRectangle(Brushes.White, 0, 0, 1000, 1000);
It is not easy to control the DPI in the Print(Preview) system.
But maybe you are going about it the wrong way. What you want is to create a (large) bitmap and then 'trick' the control in to using that bitmap as if it was the screen. See this list of links.
No need for PrintDocument.

Categories