locked
How do I get font width and height in pixels ? RRS feed

  • Question

  • Hi ,

                I want to draw text inside a bounding rect.Therefore I want to change the font size to fit the rect. I am trying to find a way to calculate the text width and height, knowing it's font.

     

                Why do different fonts with the same size have different height?

     

    Thanks, Udi Raz

    Monday, January 16, 2006 6:45 PM

Answers

  •  

    you can call the following inside of a form:

    System::Drawing::Graphics *_g = this->CreateGraphics();

    (you can also make an unmanaged call to GetTextMetrics)

    and pass the text string you want to measure, like this:

    System::Drawing::SizeF _size = _g->MeasureString(_refstring, _currfont);
    where _currfont is a previously selected or created font (also could be _currfont = this->Font)

    _size contains the height and length of _refstring so you can figure out if you need additional splits to fit
    inside of your bounding rectangle. This should be efficiently performed by a recursive function with the following signature:

    void DrawClippedText(double refwidth, double ypos, string refstring)

    this function should be called while refstring has remaining words from the original text string. ypos should be incremented every line drawn.

    For further information about fonts see

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_20dv.asp

    Monday, January 16, 2006 9:26 PM

All replies

  •  

    you can call the following inside of a form:

    System::Drawing::Graphics *_g = this->CreateGraphics();

    (you can also make an unmanaged call to GetTextMetrics)

    and pass the text string you want to measure, like this:

    System::Drawing::SizeF _size = _g->MeasureString(_refstring, _currfont);
    where _currfont is a previously selected or created font (also could be _currfont = this->Font)

    _size contains the height and length of _refstring so you can figure out if you need additional splits to fit
    inside of your bounding rectangle. This should be efficiently performed by a recursive function with the following signature:

    void DrawClippedText(double refwidth, double ypos, string refstring)

    this function should be called while refstring has remaining words from the original text string. ypos should be incremented every line drawn.

    For further information about fonts see

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_20dv.asp

    Monday, January 16, 2006 9:26 PM
  • Thanks for your help,

        Since I am using unmanaged c++, I can't use the .NET libraries.
        GetTextMatrics does not do what MeasureString Does. I want to calculate the larger font I
        can you to fit a certain rectangle and using GetTextMarics I will have run a loop that create a font in different sizes ask check whether the font fits the rectangle. I think It is not a good way.

    Udi Raz


    Wednesday, January 18, 2006 7:06 AM
  • ... And not after I tried all the font method i found on the MSDN I found that the answer for the height in all methods is the font height. The problem is that fonts don't use the whole width to draw their characters. As a result, if I create a rectangle with the size x, a certain font with the size of x will be drawn perfectly well inside my rectangle but a second font (for Hindi fonts) will be drawn very small. What I need (and start to think there is no such a method) is a method that gives me the true height of the character.

     

    Any Ideas?

    Wednesday, January 18, 2006 9:38 AM
  • the following code will take the max size for a font then it will try to minimize it till it fits. use the following code: (C# code)

     

    {// FITTING SIZE

    SizeF MyFontSize = SizeF.Empty ;

    Font  MyFont  = null ;

     

    MyFont = new Font ( "Arial", Rect.Height ) ;

    MyFontSize = g.MeasureString ( "String to draw ...", MyFont ) ;

    while ( MyFontSize.Width > MyRect.Width ||

    MyFontSize.Height > MyRect.Height )

    {

    MyFont = new Font ( "Arial", ( MyFont.Size - .01F ) ) ;

    MyFontSize = g.MeasureString ( "Eval", MyFont ) ;}

    }// FITTING SIZE

    Sunday, January 22, 2006 4:36 PM
  • I think you have misunderstood the idea, because with GetTextMetrics you can get a lot of information about the current font that helps you to do many things. For instance, if you need to fit some string inside of a bounding rectangle, just use tmMaxCharWidth field of the TEXTMETRIC structure and you will succeed fitting your string because you are using the max width a character can have (if the current font isn't a monospace font), so there is no need to loop around ;-).
    Saturday, February 11, 2006 4:03 PM
  • Hi Harold,

    Thanks for your help, I may still don't understand. Please allow me to explain myself.

    At first, I need to know the font height and not the width.

    tmHeight returns the font size, but this is not the font height. Some font's glyph does not use the whole height to draw the font, as a result the max height is much more then the real font size.

    In addition, regarding the width, tmMaxCharWidth returns a much greater value, then need.

    I would expect a method that inputs a specific char or string and retrieve the real max height and width.

    tmHeight represent the distance between the lower part of 'g' and the upper part of 'M'

    in addition, NEWTEXTMETRIC defines some more properties of the font, but not to a specific char.

    Any Suggestions ?

    Thanks, in advance,

    Udi Raz

    Sunday, February 12, 2006 3:09 PM
  • Hi ,

                I want to draw text inside a bounding rect.Therefore I want to change the font size to fit the rect. I am trying to find a way to calculate the text width and height, knowing it's font.

     

                Why do different fonts with the same size have different height?

     

    Thanks, Udi Raz

    Hai Raz ,
    I am dev. Are you able to solve this problem using any formula or method? if yes, plz post the method you follow. it will help me alot. 
    Thanks in Advance,
    Dev
    • Proposed as answer by pvdev Thursday, February 18, 2010 7:17 AM
    Friday, February 12, 2010 6:33 AM
  • Well, did anybody solve this problem?

     

    what i actually need is just to determine the number of characters i can fit inside a bounding rectangle.  if i have information from this thread, it would help me a lot. :)

     

    Wednesday, October 20, 2010 7:51 AM
  • Okay, there is a lot going on with fonts, as you can plainly see. Keepng it sorted when trying to wrest control of the screen layout from the text writing API is often a PITA from the very start. The tools we are given from MS (Like GetTextExtent et al) is only an approximation of the extent because it never actually draws the text to anything.

    First of all, let me state that the fonts used in Windows have never been the same as characters on a glass teletype, so any assumption you make based on similar character based text display will bite you in the *end*. Fonts belong to the output driver, and not to Windows. They are drawn (rasterized) in your display, or printer driver. How they are used varies somewhat, but....you have to discover this yourself over time by working with many display and printer drivers consistently and experimentally.

    Take height, for example. The height given in a TEXTMETRIC structure is not a 'one size fits all' answer for working with fonts in laying out text. It includes for example the internal leading used to keep the text vertically aligned properly. So, the notion that all you need to do is plug the height from a Textmetric structure into your code and all your problems are solved is naive.

    If you want to write code to fit text into rectangles automatically, you will eventually have to write it so that you output the text to a bitmap and get the bounds yourself manually. In fact , the best way to layout text, in my estimation (and with the requirement that the text be an exact dimension).....is to output it to an offscreen bitmap and get its bounds by locking the bits and searching them out by reading the RGB values directly.

    When you finally get a routine that does what you want without all of that....it will not run the same on all machines. I wrote one that went a long way towards meeting that goal. Then, we ran it on the production machine it was written for, and there were all kinds of issues with the size calculation, blitting from in-memory bitmaps into printer DCs, and some other issues. That led to a routine that uses a bitmap.

    The reason for this goes back to what I said about where your fonts get rasterized -- in the driver. A device context is really a special interface to the driver...display, printer, etc. So, things might work well one way for the display, but that is no guarantee that it will work properly on a printer.

    So, to answer Udi's four year old direct question.....font sizes are based on a value known as an em, which is followed to create various actual font sizes using the same ratio. Font height and width include a couple of types of spacing, which is likewise variable to a certain extent. Every font has an em value...here is a link about em values and how they relate to size...

    http://en.wikipedia.org/wiki/Em_(typography)

    There are several decent blogs about this subject...Michael S Kaplan is probably one of the world's foremost authorities on font issues, but I doubt he likes to advertise that fact, or even needs to....

    (Warning...if you don't care for puns, SIAO is not for you....)

    http://blogs.msdn.com/b/michkap/

    Raymond Chen has several informative articles about fonts, with code...

    http://blogs.msdn.com/b/oldnewthing/

     

    Wednesday, October 20, 2010 2:53 PM