Search code examples
c++windowswinapidirectwrite

DirectWrite: IDWriteFontFamily::GetFontCount


When I try to get the count of fonts in a font family by using DirectWrite, I get the wrong result. For example, when I look at the system font folder, Arial font family has 9 fonts but, GetFontCount returns 14. What is that surplus number 5? How that happens? Is that a bug or is there something I dont know or that the documentation doesn't mention? Here is a minimal repro-example.

 #include <stdio.h>
 #include <stdlib.h>
 #include <wchar.h>
    
 #include <dwrite.h>
    
 #pragma comment(lib, "dwrite")
    
 IDWriteFactory* pDWriteFactory = NULL;
 IDWriteFontCollection* pFontCollection = NULL;
 IDWriteFontFamily* pFontFamily = NULL;
 IDWriteFont* pFont = NULL;
 IDWriteFontFace* pFontFace = NULL;
    
 int main()
 {
  HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, &pDWriteFactory);
  if (FAILED(hr))
  return -1;
    
  hr = pDWriteFactory->GetSystemFontCollection(&pFontCollection, FALSE);
    
  if (FAILED(hr))
  return -2;
    
  UINT index = 0;
  BOOL exists;
  hr = pFontCollection->FindFamilyName(L"Arial", &index, &exists);
  if (FAILED(hr))
  return -3;
  hr = pFontCollection->GetFontFamily(index, &pFontFamily);
  if (FAILED(hr))
  return -4;
  UINT count;
    
  count = pFontFamily->GetFontCount();
  if (FAILED(hr))
  return -5;
  DWRITE_FONT_METRICS metrics;
  for (int i = 0; i < count; i++)
  {
  hr = pFontFamily->GetFont(i, &pFont);
  pFont->GetMetrics(&metrics);
    
  printf("%d %d %d %d\n", metrics.designUnitsPerEm, metrics.ascent, metrics.descent, metrics.lineGap);
  }
  return 0;
 }

Solution

  • DirectWrite simulates "oblique" fonts (that are not in the physical files).

    For Oblique, the slant is achieved by performing a shear transformation on the characters from a normal font. When a true italic font is not available on a computer or printer, an oblique style can be generated from the normal font and used to simulate an italic font.

    So you'll get 'Oblique', 'Narrow Oblique', 'Bold Oblique', 'Narrow Bold Oblique', 'Black Oblique' simulated fonts for a total of 14.

    If italic is available, oblique should not be used.

    You can check that using the IDWriteFontFace::GetSimulations method, on each font, which will get you back DWRITE_FONT_SIMULATIONS_OBLIQUE for those fonts.