Thread: Directwrite: Font height issues

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    54

    Directwrite: Font height issues

    I'm using Directwrite to display scrollable text in a render target, and I want to calculate how many lines of text will fit per screen.

    I've been using this code to calculate the number of lines that will fit on the RT:
    Code:
    /* pTextFormat is an IDWriteTextFormat pointer, dpi_y is the desktop's vertical dpi, and GetHeight() returns the height (in pixels) of the render target. */
    
    float size = (pTextFormat->GetFontSize()/72.0f)*dpi_y; 
    return (int)(GetHeight()/size);
    The results of the above code seem to be accurate for some fonts, but not for others, resulting in the RT "clipping" the text too early. For these other fonts, using

    Code:
    float size = pTextFormat->GetFontSize(); 
    return (int)(GetHeight()/size);
    instead seems to work.

    My problem is that I don't know how to tell which font should use which method, or why one method works for one font but not another.

    Edit:
    I'm using IDWriteTextLayouts to display the text.
    Last edited by Boxknife; 04-07-2011 at 04:45 PM. Reason: clarification

  2. #2
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    Could be wrong, but maybe this is what you should be using instead. Specifically, lineSpacing?

    Also, I'm not familiar with IDWriteTextFormat myself, but I know in the past when using things like DrawText, I was able to figure this kind of stuff out with the DT_CALCRECT option that DrawText provides. Maybe or you can find an equivalent functionality for IDWriteTextFormat.

    Okay, here's something. Check out IDWriteTextLayout->GetMetrics->layoutHeight, maybe it'll do.
    Last edited by Yarin; 04-07-2011 at 10:40 PM.

  3. #3
    Registered User
    Join Date
    Jun 2008
    Posts
    54
    Nope, none of those are it. D:

    The calculation seems to only be inaccurate for Truetype fonts.

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    In the first case, the font height is expressed in points (1/72nds of an inch). In the second case, the font height is expressed in pixels. That's the difference, though I don't know why the difference exists.

    On a 72 DPI display, a point is equal to a pixel and the two results should be the same.

    EDIT: Probably what it comes down to is vector fonts (i.e. TTF) should use the first form, and bitmapped fonts should use the second form.
    Last edited by brewbuck; 04-08-2011 at 06:57 PM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Registered User
    Join Date
    Jun 2008
    Posts
    54
    After scouring MSDN, I found an answer.

    You have to do something like:
    Code:
       IDWriteFontCollection* collection;
        TCHAR name[64]; UINT32 findex; BOOL exists;
        pTextFormat->GetFontFamilyName(name, 64);
        pTextFormat->GetFontCollection(&collection);
        collection->FindFamilyName(name, &findex, &exists); 
        IDWriteFontFamily *ffamily;
        collection->GetFontFamily(findex, &ffamily);
        IDWriteFont* font;
        ffamily->GetFirstMatchingFont(pTextFormat->GetFontWeight(), pTextFormat->GetFontStretch(), pTextFormat->GetFontStyle(), &font);
        DWRITE_FONT_METRICS metrics;
        font->GetMetrics(&metrics);
        float ratio = pTextFormat->GetFontSize() / (float)metrics.designUnitsPerEm;
        float size = (metrics.ascent + metrics.descent + metrics.lineGap) * ratio;
        float height = GetHeight();
        int retval = static_cast<int>(height/size);
        ffamily->Release();
        collection->Release();
        font->Release();
        return retval; //retval is the number of lines of text that will fit in GetHeight().
    This is accurate for all the fonts I've been able to test.

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    It helps understanding if you consider the units.

    The font size is in "design units." If you divide this by "design units per em" you get something measured in ems. An em is something which is as high as the current point size. If you multiply that by the point size, you get the height of an em as measured in points. Dividing this by 72 points per inch yields inches. Multiplying that by target DPI gives pixels.

    The math posted above does in fact work all that out, but IMHO does so in a way that makes it harder to understand WHY it works.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Error: expected identifier or ‘(’ before ‘{’ token
    By jpcanaverde in forum C Programming
    Replies: 66
    Last Post: 06-08-2010, 12:53 PM
  2. DirectX | Drawing text
    By gavra in forum Game Programming
    Replies: 4
    Last Post: 06-08-2009, 12:23 AM
  3. problem with my font manager
    By hannibar in forum C Programming
    Replies: 1
    Last Post: 03-07-2006, 08:03 AM
  4. char copy
    By variable in forum C Programming
    Replies: 8
    Last Post: 02-06-2005, 10:18 PM
  5. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM