1

I am working on a GDI to DirectWrite migration project. I want to calculate width of each unicode character , on GDI this is acomplished using GetCharWidth. On msdn blog i found that replacement for GetCharWidth of GDI is GetDesignGlyphMetrics .

Can anyone tell me how to use this function GetDesignGlyphMetrics in order to get DWRITE_GLYPH_METRICS?

How to instantiate its first parameter UINT16 const* glyphIndices?

Chandan
  • 13
  • 3

1 Answers1

4

You can get the glyphindices by IDWriteFontFace::GetGlyphIndices

I pick some code from my project, this is just an example show you how to use this function, if you want to use it in your project, you should do some refactoring, move the XXXCreate function to the initialize part of your code. for example, you don't need to create the DWriteFacotry every time when you call this function(GetCharWidth). and release the dynamic array to avoid memory leaks.

IDWriteFactory*         g_pDWriteFactory    = NULL;
IDWriteFontFace*        g_pFontFace         = NULL;
IDWriteFontFile*        g_pFontFile         = NULL;
IDWriteTextFormat*      g_pTextFormat       = NULL;

VOID GetCharWidth(wchar_t c)
{
    // Create Direct2D Factory
    HRESULT hr = D2D1CreateFactory(
        D2D1_FACTORY_TYPE_SINGLE_THREADED,
        &g_pD2DFactory
        );
    if(FAILED(hr))
    {
        MessageBox(NULL, L"Create Direct2D factory failed!", L"Error", 0);
        return;
    }

    // Create font file reference
    const WCHAR* filePath = L"C:/Windows/Fonts/timesbd.ttf";
    hr = g_pDWriteFactory->CreateFontFileReference(
        filePath,
        NULL,
        &g_pFontFile
        );
    if(FAILED(hr))
    {
        MessageBox(NULL, L"Create font file reference failed!", L"Error", 0);
        return;
    }

    // Create font face
    IDWriteFontFile* fontFileArray[] = { g_pFontFile };
    g_pDWriteFactory->CreateFontFace(
        DWRITE_FONT_FACE_TYPE_TRUETYPE,
        1,
        fontFileArray,
        0,
        DWRITE_FONT_SIMULATIONS_NONE,
        &g_pFontFace
        );
    if(FAILED(hr))
    {
        MessageBox(NULL, L"Create font file face failed!", L"Error", 0);
        return;
    }

    wchar_t textString[] = {c, '\0'};

    // Get text length
    UINT32 textLength = (UINT32)wcslen(textString);

    UINT32* pCodePoints     = new UINT32[textLength];
    ZeroMemory(pCodePoints, sizeof(UINT32) * textLength);

    UINT16* pGlyphIndices   = new UINT16[textLength];
    ZeroMemory(pGlyphIndices, sizeof(UINT16) * textLength);

    for(unsigned int i = 0; i < textLength; ++i)
    {
        pCodePoints[i] = textString[i];
    }

    // Get glyph indices
    hr = g_pFontFace->GetGlyphIndices(
        pCodePoints,
        textLength,
        pGlyphIndices
        );
    if(FAILED(hr))
    {
        MessageBox(NULL, L"Get glyph indices failed!", L"Error", 0);
        return;
    }

    DWRITE_GLYPH_METRICS* glyphmetrics = new DWRITE_GLYPH_METRICS[textLength];
    g_pFontFace->GetDesignGlyphMetrics(pGlyphIndices, textLength, glyphmetrics);

    // do your calculation here

    delete []glyphmetrics;
    glyphmetrics = NULL;
}
zdd
  • 8,258
  • 8
  • 46
  • 75
  • Could u please tell me, How to use glyphmetrics further, Basically i wants to calculate the width of each character so that i can update the cursor position. – Chandan Jul 09 '14 at 09:50
  • You can take a look at the members of [DWRITE_GLYPH_METRICS](http://msdn.microsoft.com/en-us/library/windows/desktop/dd368084(v=vs.85).aspx) – zdd Jul 09 '14 at 11:32
  • I am using following code to calculate the width of a given text, n_width[index] = (glyphmetrics->advanceWidth + glyphmetrics->leftSideBearing + glyphmetrics->rightSideBearing) *fontSize/fontMetrics.designUnitsPerEm; But this seems not working for each character...... is there any other formula for this ? – Chandan Aug 01 '14 at 15:36
  • @Chandan: The 'width' of each character is just the advanceWidth, and the *visual* width is advanceWidth - leftSideBearing - rightSideBearing (not +). – Dwayne Robinson Jul 02 '15 at 09:18
  • It's worth noting that this code is **not** suitable for unicode text (it's just assigning 16-bit characters to 32-bit characters, without performing conversion). See this answer for how to actually convert the characters - https://stackoverflow.com/a/23920015/986 – Mark Ingram Mar 04 '19 at 12:24