locked
How to get physical font data? RRS feed

  • Question

  • Hello everyone. I'm writing a program to deal with TypeTrue fonts. What I want to do is to get the font data from a device context. The following code works perfectly:


    HFONT f = CreateFont(-11, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, _T("Tahoma"));
    SelectObject(hdc, f);
    DWORD fontLen = GetFontData(hdc, 0, 0, NULL, 0);


    However, when switch "Tahoma" to "System", like this:



    HFONT f = CreateFont(-11, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, _T("System"));
    SelectObject(hdc, f); DWORD fontLen = GetFontData(hdc, 0, 0, NULL, 0);


    fontLen is always returned as GDI_ERROR. Obviously the "System" font is special and seems like a virtual font, since there is no corresponding font file in the system. My question is, could there be a way to get the font data for System? Where can I find more information about this special font, and other virtual fonts as Fixedsys? Thank you!
    Tuesday, September 15, 2009 10:50 PM

Answers

  • The system font is a device font.  Dates back from the Windows 2.x when outline fonts didn't exist yet and fonts were defined by pixels, mapped directly to the screen.  In c:\windows\fonts, they are the .fon files, TrueType are the .ttf files.

    Hans Passant.
    • Marked as answer by nobugz Sunday, September 27, 2009 12:31 AM
    Tuesday, September 15, 2009 11:31 PM

All replies

  • GetFontData() returns data only for true type fonts. I believe the SYSTEM_FONT is not true type.

    You can verify this by selecting this font into a device context and calling the function GetTextMetrics().

    If the tmPitchAndFamily member of the TEXTMETRICS structure passed to the function doesn't contain the bit TPMF_TRUETYPE on, the font is not true type.
    Tuesday, September 15, 2009 11:22 PM
  • The system font is a device font.  Dates back from the Windows 2.x when outline fonts didn't exist yet and fonts were defined by pixels, mapped directly to the screen.  In c:\windows\fonts, they are the .fon files, TrueType are the .ttf files.

    Hans Passant.
    • Marked as answer by nobugz Sunday, September 27, 2009 12:31 AM
    Tuesday, September 15, 2009 11:31 PM
  • Oh, I see, svgasys.fon and svgafix.fon. So they are raster fonts, how can I forget! Then I still wonder if there is way to get the font data from memory so that I can interpret it with my own code. Thank you and nobugz and Belloc!
    Wednesday, September 16, 2009 12:12 AM
  • If you select any font to a device context and call GetTextMetrics() you get the information for that font.
    Wednesday, September 16, 2009 12:21 AM
  • Thanks. However, GetTextMetrics() gives me a TEXTMETRIC structure. What I need is an equivalent of GetFontData() for raster fonts, which gives me the binary data of the .fon files. Do you know anything about this?
    Wednesday, September 16, 2009 2:00 AM
  • I constructed a LOGFONT with lfWeight = 600 (SEMIBOLD) and face is Tahoma. Select this font into a DC, and then GetFontData(). The function gives me the data of tahoma.ttf, since tahomabd.ttf is for BOLD (lfWeight == 700). However, it seems the default behavior of Windows in this case is to use the bold font tahomabd.ttf instead. How can I maintain the compatibility with Windows? I think an approach to directly access the system font table could be the best, but I cannot find a way to do this. I cannot know what is the physical filename for a logical font "Tahoma (Regular)". The registry branch HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts is not enough, as there is no entry for System, Fixedsys, MS Shell Dlg, etc.

    Thanks!
    Wednesday, September 16, 2009 5:56 AM
  • You're all over the road with this question.  GetFontData() is intended for font embedding, that's a non-starter for device fonts.  There is no direct mapping from a logical TrueType font to a physical .ttf file, Tahoma is made from 4 of them.  What do you really want to accomplish?

    Hans Passant.
    Wednesday, September 16, 2009 8:57 AM
  • Try something like freetype
    Wednesday, September 16, 2009 9:31 PM
  • You're all over the road with this question.  GetFontData() is intended for font embedding, that's a non-starter for device fonts.  There is no direct mapping from a logical TrueType font to a physical .ttf file, Tahoma is made from 4 of them.  What do you really want to accomplish?

    Hans Passant.
    OK. Actually I'm interested in FreeType. I have a small program, that the user can input a string as the font face, like "Tahoma", and check some options like Bold or Italic or both. Then my program will load the font into FreeType, and render it. As FreeType needs the real font file ("tahoma.ttf") to get the glyphs, I need the filename mapping from "Tahoma" + Bold to C:\Windows\Fonts\tahomabd.ttf, or "Tahoma" + Regular to C:\Windows\Fonts\tahoma.ttf. That why I want the access to the system font table, and found  GetFontData(). With CreateFont() and GetFontData(), you can get the font file's binary data without specifying the filename, and feed the data to FreeType. Unfortunately, it does not work for the raster fonts as System and Fixedsys.

    Then I thought, as the program itself uses Tahoma as the interface font, the font must have been loaded into the memory space of the process. When the user want to render Tahoma, maybe directly get that memory mapping instead of load the physical file is a better idea. However, I don't find a way to get the memory address. The HFONT returned by CreateFont is higher than 0x80000000, the kernel reserved space. Probably the font data are also mapped to the kernel space.

    By the way, I think in a typical Windows, there are only 2 files for Tahoma, tahoma.ttf for regular and tahomabd.ttf for bold. Are there another two files for Tahoma?

    Of course, if you have better idea for this scenario, please share. Thank you!
    Wednesday, September 16, 2009 11:35 PM
  • Try something like freetype
    That's what I want to do. FreeType needs physical filename to create a FT_Face object. Is there a way to create FT_Face with only logical font facename?
    Wednesday, September 16, 2009 11:36 PM