Announcement

Collapse
No announcement yet.

Fonts finding font name from file not installed

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Fonts finding font name from file not installed

    https://stackoverflow.com/questions/...me-of-ttf-file

    HERE IS HOW TO DO IT I THINK

    THE QUESTION Lets say there is a .ttf (True Type Font) file. You can install it on windows with a click. The real name of the font is not the text that is before the .tff (lets say SuperFont.ttf => so the name is not "SuperFont" - it could be, but mostly not). I would like to read the .tff (somehow?) and get the name (without installing the font) of the font. Any ideas?

    ANSWERS 2

    2 Answers

    You'll need to add the font to a private collection (PrivateFontCollection), then request the FontFamily instance and get its Name property.
    Like this:

    PrivateFontCollection fontCol = new PrivateFontCollection(); fontCol.AddFontFile(@"PATH TO FONT"); Console.WriteLine(fontCol.Families[0].Name);You'll need the namespaces:

    using System.Drawing; using System.Drawing.Text;MSDN: PrivateFontCollection, FontFamily

    answered Aug 9 '12 at 14:14
    • 3

      This doesn't install the font. Although MSDN uses the term "install" they're using it lightly. "This is a temporary font install that does not affect the system-installed collection." Install here basically means "loaded". – Matt Razza Aug 9 '12 at 14:18
    • This gets the font family name (e.g. "Open Sans"), but not the full name with the style. For example, every .ttf file for open sans will have the name "Open Sans", not "Open Sans Italic" or "Open Sans Bold". – Triynko Dec 17 '15 at 20:23
    3

    Here is the another code to extract fontname without using System.Drawing dll

    foreach (FontFamily fontFamily in Fonts.GetFontFamilies("file:///D:/MyFonts/")) { string name = fontFamily .ToString().Split('#')[fontFamily .ToString().Split('#').Count() - 1]; }

    THANKS FOR ANY HELP

  • #2
    Here's some well documented code that should be fairly easy to convert to PB:

    https://www.codeproject.com/Articles...-from-TTF-File


    Edit:
    Doh!
    I ( you / we ? ) should have searched the forums first.
    Mark Bullivant did the conversion for us a couple of years ago.

    First hit when googling:
    site:powerbasic.com font name from file
    https://forum.powerbasic.com/forum/u...rom-a-ttf-file

    Comment


    • #3

      found in pascal ??
      code:
      {$APPTYPE Console}

      {$R *.Res}

      uses
      Windows,
      SysUtils;


      Function GetFontResourceInfo(lpszFilename: PChar; Var cbBuffer: Dword; lpBuffer: PChar; dwQueryType: Dword): Dword; StdCall; External 'gdi32.dll' name 'GetFontResourceInfoW';

      procedure ListFonts;
      Const
      QFR_DESCRIPTION =1;
      Var
      FileRec : TSearchRec;
      cbBuffer : Dword;
      lpBuffer: Array[0..MAX_PATH-1] Of Char;
      Begin
      If FindFirst('C:\Windows\Fonts\*.*', faNormal, FileRec) = 0 then
      Try
      repeat
      cbBuffer:=SizeOf(lpBuffer);
      GetFontResourceInfo(PWideChar('C:\Windows\Fonts\'+FileRec.Name), cbBuffer, lpBuffer, QFR_DESCRIPTION);
      Writeln(Format('%s - %s',[FileRec.Name ,lpBuffer]));
      Until FindNext(FileRec) <> 0;
      Finally
      FindClose(FileRec);
      End;
      End;


      Begin
      Try
      ListFonts;
      except
      On E: Exception Do
      Writeln(E.ClassName, ': ', E.Message);
      End;
      Readln;

      maybe able to convert

      thanks for help

      Comment


      • #4
        I already had mine...
        Note, this is an undocumented api...

        Code:
        #COMPILE EXE '#Win#
        %UNICODE = 1
        #DIM ALL
        #INCLUDE "Win32Api.inc"
        
        %QFR_0           = 0 'DWORD or LPVOID unknown
        %QFR_DESCRIPTION = 1 'The function provides a string that an NT-based operating system will use to describe the font file. A null-terminated Unicode string is written to the buffer pointed to by lpBuffer.
        %QFR_LOGFONT     = 2 'Array of LOGFONT
        %QFR_PDEV        = 3 'PDEV ?
        %QFR_FONTFILE    = 4 'scalable font file name
        %QFR_5           = 5 'DWORD Windows XP: Always returns 0
        
        'BOOL GetFontResourceInfo(
        '  LPCTSTR lpszFilename, // font file name
        '  LPDWORD cbBuffer,     // size of buffer for resouce information
        '  LPVOID lpvBuffer,     // buffer for returned resouce information
        '  DWORD dwType,         // resouce information type
        ');
        
        DECLARE FUNCTION GetFontResourceInfo LIB "Gdi32.dll" ALIAS "GetFontResourceInfoW" _
        (BYVAL lpszFilename AS WSTRING, BYREF cbBuffer AS DWORD, BYVAL lpvBuffer AS DWORD, BYVAL dwType AS DWORD) AS DWORD
        '_____________________________________________________________________________
        
        FUNCTION PBMAIN()
         LOCAL pLogFont          AS LOGFONTW POINTER
         LOCAL pzw               AS WSTRINGZ POINTER
         LOCAL zwFontFileName    AS WSTRING
         LOCAL zwBuffer          AS WSTRING
         LOCAL zwLog             AS WSTRING
         LOCAL BufferSize        AS DWORD
         LOCAL dwType            AS DWORD
         LOCAL index             AS LONG
         LOCAL LogFontCount      AS LONG
         LOCAL FontResourceAdded AS LONG
        
         'zwFontFileName = "C:\Windows\Fonts\Roman.fon"
         'zwFontFileName = "Consolai.ttf"
         zwFontFileName  = "C:\Windows\Fonts\Cambria.ttc" 'Adjust path if needed
        
         'FontResourceAdded = AddFontResourceExW((zwFontFileName), %FR_NOT_ENUM, 0) 'UnREM for unInstalled font
         zwLog             = zwFontFileName & $CRLF & $CRLF
        
         FOR dwType = %QFR_DESCRIPTION TO %QFR_FONTFILE
           zwBuffer   = NUL$(2048)
           pzw        = STRPTR(zwBuffer)
           BufferSize = LEN(zwBuffer)
        
           IF GetFontResourceInfo(zwFontFileName, BufferSize, pzw, dwType) THEN
        
             SELECT CASE dwType
        
               CASE %QFR_0 '0, DWORD or LPVOID unknown
        
               CASE %QFR_DESCRIPTION '1, fileName to FontName, scalable font file name
                 zwLog &= "QFR_DESCRIPTION" & $CRLF & _
                          "[" & @pzw & "]"  & $CRLF & $CRLF
        
               CASE %QFR_LOGFONT '2, array of LOGFONT
                 LogFontCount = BufferSize / SIZEOF(LOGFONTW)
                 zwLog &= "QFR_LOGFONT" & $CRLF & STR$(LogFontCount) & _
                          " logfont" & IIF$(LogFontCount > 1, "s", "") & " returned" & $CRLF
                 pLogFont = STRPTR(zwBuffer)
                 FOR index = 0 TO LogFontCount - 1
                   zwLog &= "[" & @pLogFont[index].lfFaceName & "]" & $CRLF
                 NEXT
                 zwLog &= $CRLF
        
               CASE %QFR_PDEV '3 pDev
        
               CASE %QFR_FONTFILE '4, scalable font file name
                 zwLog &= "QFR_FONTFILE"   & $CRLF & _
                          "[" & @pzw & "]" & $CRLF & $CRLF
        
               CASE %QFR_5 '5 DWORD Windows XP: Always returns 0
        
             END SELECT
        
           END IF
         NEXT
         IF FontResourceAdded THEN RemoveFontResourceExA((zwFontFileName), %FR_NOT_ENUM, 0)
         MessageBox(%HWND_DESKTOP, (zwLog), "GetFontResourceInfo()", %MB_OK OR %MB_TOPMOST)
        
        END FUNCTION
        '_____________________________________________________________________________
        '
        Last edited by Pierre Bellisle; 14 Mar 2020, 02:07 AM.

        Comment


        • #5
          GetFontResourceInfoW is an "undocumented" API function and as such may or may not be available on any particular OS version and may disappear with any OS update. Use at your own risk.

          Comment


          • #6
            @ James,

            Note that if you want to use GetFontResourceInfo() with an uninstalled font,
            you will have to call AddFontResourceEx(%FR_NOT_ENUM) / RemoveFontResourceEx(%FR_NOT_ENUM)

            Above example updated...

            Comment


            • #7
              Pierre

              Connais tu l'utilisation de fontes privées ?
              C'est ce que j'utilise dans GDImage, de cette façon je suis certain d'avoir toujours le même rendu visuel sans me soucier de savoir si les fontes sont installées ou non.
              Patrice Terrier
              www.zapsolution.com
              www.objreader.com
              Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

              Comment


              • #8
                Bonjour Patrice,
                Si tu fais allusion à PrivateFontCollection, je ne peux que dire que je n'ai pas exploré cette classe.
                Par contre, tu pense à la caractéristique FR_PRIVATE offerte par l'api AddFontResourceEx(),
                malheureusement, elle ne permet pas le bon fonctionnement de l'api GetFontResourceInfo(), de là mon choix de FR_NOT_ENUM.

                Hey Patrice,
                If you are thinking about PrivateFontCollection, I never used this class.
                If you are talking about AddFontResourceEx flag FR_PRIVATE then sadly,
                GetFontResourceInfo() refused to work with it, so I choose FR_NOT_ENUM.
                AddFontResourceEx will install the font temporarily only for the current session.

                Comment


                • #9
                  Pierre

                  No need to use a class, i prefer to use directly the full GDIPLUS Flat API, something like this.

                  Code:
                  struct PRIVATEFONT {
                      WCHAR    file[LF_FACESIZE];
                      WCHAR    name[LF_FACESIZE];
                      LONG_PTR fam;
                  } ;
                  
                  vector<PRIVATEFONT> g_Font;
                  LONG_PTR g_FontCollection = 0;
                  
                  LONG_PTR LoadPrivateFont (IN WCHAR* szFileName) {
                      LONG_PTR nRet = 0;
                      WCHAR szName[LF_FACESIZE] = {0};
                      WCHAR szPath[MAX_PATH] = {0};
                      WCHAR szFile[MAX_PATH] = {0};
                      zSplitN (szFileName, &szPath[0], &szFile[0]);
                  
                      long K, UB = (long) g_Font.size();
                      if (UB > 0) {
                          for (K = 0; K < UB; K++) {
                              if (_wcsicmp(g_Font[K].file, szFile) == 0) { nRet = g_Font[K].fam; break;}
                          }
                      }
                  
                      if (nRet == 0) {
                          if (g_FontCollection) {
                              if (GdipPrivateAddFontFile(g_FontCollection, szFileName) == 0) {
                                  long nCount = 0, numFound = 0, U = 0, UK = 0, nFound = 0;
                                  GdipGetFontCollectionFamilyCount(g_FontCollection, nCount);
                                  if (nCount > 0 ) {
                                      LONG_PTR* fontFamilyList = new LONG_PTR[nCount];
                                      if (GdipGetFontCollectionFamilyList(g_FontCollection, nCount, fontFamilyList[0], numFound) == 0) {
                                          if (numFound > 0) {
                                              if (UB > 0) { // Make sure that we got a different handle #.
                                                  UK = numFound; numFound = 0;
                                                  for (K = 0; K < UK; K++) {
                                                      nFound = 0;
                                                      for (U = 0; U < UB; U++) {
                                                           if (fontFamilyList[K] == g_Font[U].fam) { nFound = -1; }
                                                      }
                                                      if (nFound == 0) { numFound = K + 1; break; } // Ok that is a new one.
                                                  }
                                              }
                                              if (numFound > 0) {
                                                  GdipGetFamilyName(fontFamilyList[numFound - 1], szName, LANG_NEUTRAL);
                                                  g_Font.resize(UB + 1);
                                                  wcscpy_s(g_Font[UB].file, szFile);
                                                  wcscpy_s(g_Font[UB].name, szName);
                                                  g_Font[UB].fam = fontFamilyList[numFound - 1];
                                                  nRet = g_Font[UB].fam;
                                              }
                                          }
                                      }
                                      delete [] fontFamilyList;
                                  }
                              }
                          }
                      }
                      return nRet;
                  }
                  
                  LONG_PTR zUsePrivateFont(IN WCHAR* UseFont, IN float useSize) { // dllexport AS LONG_PTR
                      LONG_PTR nFontRet = 0;
                      LONG_PTR nFam = 0, hFont = 0;
                      if (UsePrivateFont(UseFont)) {
                          nFam = LoadPrivateFont(UseFont); // Create a PrivateFont
                          if (nFam) {
                              //float useSize = 18.0f;
                              if (GdipCreateFont(nFam, useSize, FontStyleRegular, UnitPixel, hFont) == 0) { nFontRet = hFont; }
                          }
                      }
                      return nFontRet;
                  }
                  and a quick translation into PowerBASIC (you will have to write the zUseprivateFont yourself, but that's the easiest part)

                  Code:
                  TYPE PRIVATEFONT
                      pfFile AS ASCIIZ * MAX_PATH
                      pfName AS ASCIIZ * 64
                      pfFam AS DWORD
                  END TYPE
                  
                  GLOBAL g_FontCollection AS DWORD
                  GLOBAL g_Font() AS PRIVATEFONT
                  
                  FUNCTION UsePrivateFont(BYVAL sUseFont AS STRING) AS BYTE
                      LOCAL bRet AS BYTE
                      IF (LEN(sUseFont) > 3) THEN
                          LOCAL sExt AS STRING
                          sExt = LCASE$(RIGHT$(sUseFont, 4)) + "."
                          IF INSTR(1, ".ttf.otf.", sExt) THEN bRet = 1
                      END IF
                      FUNCTION = bRet
                  END FUNCTION
                  
                  FUNCTION LoadPrivateFont (BYVAL sFileName AS STRING) AS DWORD
                      LOCAL nRet AS DWORD
                      LOCAL K, UB AS LONG
                      LOCAL nCount, numFound, U, UK, nFound AS LONG
                      LOCAL sPath, sFile AS STRING
                      LOCAL szName AS ASCIIZ * 64
                      zSplitN(sFileName, sPath, sFile)
                      sFile = LCASE$(sFile)
                  
                      UB = UBOUND(g_Font)
                      IF (UB > 0) THEN
                          FOR K = 1 TO UB
                              IF g_Font(K).pfFile = sFile THEN nRet = g_Font(K).pfFam
                          NEXT
                      END IF
                  
                      IF (nRet = 0) THEN
                          IF (g_FontCollection) THEN
                              IF GdipPrivateAddFontFile(g_FontCollection, UCODE$(sFileName)) = 0 THEN
                                  nCount = 0: numFound = 0: U = 0: UK = 0: nFound = 0
                                  GdipGetFontCollectionFamilyCount(g_FontCollection, nCount)
                                  IF (nCount > 0 ) THEN
                                      REDIM fontFamilyList(1 TO nCount) AS DWORD
                                      IF (GdipGetFontCollectionFamilyList(g_FontCollection, nCount, BYVAL VARPTR(fontFamilyList(1)), numFound) = 0) THEN
                                          IF (numFound > 0) THEN 
                                              IF (UB > 0) THEN '// Make sure that we got a different handle #. 
                                                  UK = numFound: numFound = 0
                                                  FOR K = 1 TO UK
                                                      nFound = 0
                                                      FOR U = 1 TO UB
                                                          IF fontFamilyList(K) = g_Font(U).pfFam THEN nFound = -1
                                                      NEXT
                                                      IF (nFound = 0) THEN numFound = K: EXIT FOR '// Ok that is a new one.
                                                  NEXT
                                              END IF
                                              IF (numFound > 0) THEN
                                                  GdipGetFamilyName(BYVAL VARPTR(fontFamilyList(numFound)), szName, 0)
                  
                                                  UB = MAX&(UB + 1, 1)
                                                  REDIM PRESERVE g_Font(1 TO UB) AS PRIVATEFONT
                  
                                                  g_Font(UB).pfFile = sFile
                                                  g_Font(UB).pfName = ACODE$(szName)
                                                  g_Font(UB).pfFam = fontFamilyList(numFound)
                                                  nRet = g_Font(UB).pfFam
                                              END IF
                                          END IF
                                      END IF
                                      ERASE fontFamilyList()
                                  END IF
                              END IF
                          END IF
                      END IF
                      FUNCTION = nRet
                  
                  END FUNCTION
                  Patrice Terrier
                  www.zapsolution.com
                  www.objreader.com
                  Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                  Comment


                  • #10
                    Yep,
                    Nice one Patrice, your gdi+ flat api code work great, it report the font name. No installation required.
                    Seeing the gdi api calling sequences is also good to know what to do and when to do it.

                    For those who wan to try, remember to use GdiplusStartup() and GdiplusShutdown().
                    You will also need to create an empty collection, I used GdipNewPrivateFontCollection(g_FontCollection).

                    Comment

                    Working...
                    X