Announcement

Collapse
No announcement yet.

Enumerate font styles..

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

  • Enumerate font styles..

    Does anyone know of a good way to find out all possible font styles for
    a TrueType font? Found that enumerating the fonts isn't enough - some
    can be bold and italic, but can't be both at same time, etc.

    Found a working solution by creating a font of each desired style, select
    into a DC, look at textmetric members and then de-select/delete. If they
    match what I wanted to create, add to list, else font can't be this style.

    Means I have to do this at least four times for each font name, FW_NORMAL
    and FW_BOLD, both with tmItalic on/off. For more exact table, would have
    to run through all tmWeigth possibilites, from FW_DONTCARE to FW_BLACK, but..

    Is fast enough though - instant, but code looks terrible. Maybe I have missed
    some clever little API that returns all valid styles for a font name in one take..?


    ------------------

  • #2
    Call EnumFontFamilies and define an callback function EnumFontFamProc

    The second parameter of the callback proc point to a Struct NEWTEXTMETRIC

    From that Struct you can obtain the physical attributes of the font
    HTH



    [This message has been edited by Gafny Jacob (edited October 14, 2001).]

    Comment


    • #3
      Yes Gafny, I tried, but some fonts says "bold italic", but no way to
      tell how these styles can be combined. I have some fonts that can be
      bold and bold+italic, but not italic. Other can be bold or italic, but
      not both, etc. Some fonts says nothing at all.

      Think reason is because some fonts are old and don't have all proper
      flags and structure members set. Only sure way so far, seems to be by
      physically try the fonts. Can do like MS and probably use enumeration
      way, but also get same inconsistent result. Like MS font dialog tells
      me some fonts can have all styles, when in reality, they can't..

      Have it working here, but thought there may be some easier way out.
      After many tests, don't think there is.


      ------------------

      Comment


      • #4
        Include is a short sample to find fonts attributes

        Code:
        $COMPILE  EXE
        $INCLUDE  "WIN32API.INC"
        
        FUNCTION EnumFontFam(ef AS ENUMLOGFONT, tm AS NEWTEXTMETRIC, BYVAL FontType AS LONG, lpData AS LONG) AS LONG
            LISTBOX ADD lpData, 102, ef.elfStyle
            FUNCTION = 1
        END FUNCTION
           
        SUB SetFontAttribute(hDlg AS LONG)
            LOCAL hDc      AS LONG
            LOCAL i        AS LONG
            LOCAL FntName  AS ASCIIZ * 33
            LOCAL pSize    AS LONG
        
            CONTROL SEND hDlg, 101, %CB_GETCURSEL ,0, 0, TO i
            CONTROL SEND hDlg, 101, %CB_GETLBTEXT ,i, VARPTR(Fntname)
            hDC = GetDC(%HWND_DESKTOP)
            LISTBOX RESET hDlg, 102
            EnumFontFamilies hDC,  FntName, CODEPTR(EnumFontFam), BYVAL VARPTR(hDlg)
            ReleaseDC %HWND_DESKTOP, hDC
        END SUB
        
        FUNCTION EnumFontName(lf AS LOGFONT, tm AS NEWTEXTMETRIC, BYVAL FontType AS LONG, lpData AS LONG) AS LONG
          LOCAL zText AS ASCIIZ * 256
          IF (Tm.tmPitchAndFamily AND %TMPF_TRUETYPE) = %TMPF_TRUETYPE THEN
             zText = lf.lfFaceName
             CONTROL SEND lpData, 101, %CB_ADDSTRING, 0, VARPTR(zText)
          END IF
          FUNCTION = 1
        END FUNCTION
        
        CALLBACK FUNCTION DlgProc
            LOCAL hDc  AS LONG
            LOCAL hDlg AS LONG
        
            SELECT CASE CBMSG
                CASE %WM_INITDIALOG
                   hDC = GetDC(%HWND_DESKTOP)
                   hDlg = CBHNDL
                   EnumFonts hDC,  BYVAL %NULL, CODEPTR(EnumFontName), BYVAL VARPTR(hDlg)
                   ReleaseDC %HWND_DESKTOP, hDC
                   CONTROL SEND CBHNDL, 101, %CB_SETCURSEL, 0, 0
                   CALL SetFontAttribute(CBHNDL)
                CASE %WM_COMMAND
                   IF (HIWRD(CBWPARAM) = %CBN_SELENDOK) AND (LOWRD(CBWPARAM) = 101) THEN
                      CALL SetFontAttribute(CBHNDL)
                   END IF
            END SELECT
        END FUNCTION
        
        FUNCTION PBMAIN()  AS LONG
           LOCAL hDlg  AS LONG
           DIALOG NEW 0, "Font Test" ,,, 180, 50, %DS_CENTER OR %WS_CAPTION OR %WS_SYSMENU TO hDlg
           CONTROL ADD COMBOBOX, hDlg, 101, , 1, 2, 120, 100, %CBS_DROPDOWNLIST OR %WS_VSCROLL OR %WS_TABSTOP
           CONTROL ADD LISTBOX, hDlg, 102, , 123, 2, 55, 45,%WS_BORDER OR %LBS_NOINTEGRALHEIGHT, %WS_EX_CLIENTEDGE
           DIALOG SHOW MODAL hDlg CALL DlgProc
        END FUNCTION

        ------------------

        Comment


        • #5
          Thank you Gafny. Yes, I have also tried EnumFontFamiliesEx to get
          eventual scripts, etc, but none of these gives 100% result. Talked
          to a fellow who's done a lot of work with fonts and he says, "only
          sure way is by physically testing each style. Reason is, some fonts
          are old, others are simply not created in proper way - they work,
          but don't give out correct info. Only thing that is sure, is that
          you can never be sure when it comes to Windows' font handling.."

          Can see that here. Some fonts only says "bold". Okay, but can they
          be bold+italic? No way to tell without testing. Some can, some can't.
          Many says "Regular" or "Normal", but when tested, some of them can't
          be bold, or italic, or whatever. Inconsistent, so I'll stick to my
          ugly code, because it works..


          ------------------

          Comment


          • #6
            Wrapped up a mix of my code and Gafny's. The "GetFontStyle" function
            is only way I have found that gives correct available styles. Maybe
            useful in case someone else also want to do own font dialog..
            Code:
            #COMPILE EXE
            #INCLUDE "WIN32API.INC"
             
            DECLARE CALLBACK FUNCTION DlgProc
            DECLARE SUB GetFontStyles(BYVAL hWnd AS LONG, BYVAL sFontName AS STRING)
            DECLARE FUNCTION MakeFontEx(BYVAL sFont AS STRING, BYVAL PointSize AS LONG, _
                                        BYVAL fBold AS LONG, BYVAL fItalic AS LONG, BYVAL fUnderline AS LONG) AS LONG
             
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' Main entrance
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            FUNCTION PBMAIN()  AS LONG
              LOCAL hDlg  AS LONG
             
              DIALOG NEW 0, "Font Test" ,,, 180, 50, %DS_CENTER OR %WS_CAPTION OR %WS_SYSMENU TO hDlg
              CONTROL ADD COMBOBOX, hDlg, 101, , 1, 2, 120, 100, _
                                    %CBS_DROPDOWNLIST OR %WS_VSCROLL OR %WS_TABSTOP OR %CBS_SORT
              CONTROL ADD LISTBOX, hDlg, 102, , 123, 2, 55, 45, _
                                    %LBS_NOINTEGRALHEIGHT OR %WS_TABSTOP, %WS_EX_CLIENTEDGE
              
              DIALOG SHOW MODAL hDlg CALL DlgProc
            END FUNCTION
             
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' Main dialog's callback procedure
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            CALLBACK FUNCTION DlgProc
              LOCAL hDc  AS LONG, hDlg AS LONG, txt AS STRING
             
              SELECT CASE CBMSG
                  CASE %WM_INITDIALOG
                     hDlg = CBHNDL
                     hDC = GetDC(%HWND_DESKTOP)
                       EnumFontFamilies hDC, BYVAL %NULL, CODEPTR(EnumFontNames), BYVAL VARPTR(hDlg)
                     ReleaseDC %HWND_DESKTOP, hDC
                     CONTROL SEND CBHNDL, 101, %CB_SETCURSEL, 0, 0
                     COMBOBOX GET TEXT CBHNDL, 101 TO txt
                     CALL GetFontStyles(CBHNDL, txt)
             
                  CASE %WM_COMMAND
                     IF CBCTLMSG = %BN_CLICKED AND CBCTL = %IDCANCEL THEN
                        DIALOG END CBHNDL
                     ELSEIF CBCTLMSG = %CBN_SELENDOK AND CBCTL = 101 THEN
                        COMBOBOX GET TEXT CBHNDL, 101 TO txt
                        CALL GetFontStyles(CBHNDL, txt)
                     END IF
             
              END SELECT
            END FUNCTION
             
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' Get available font styles by testing if they can be created
            ' Seems to be only 100% sure way to get working styles..
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            SUB GetFontStyles(BYVAL hWnd AS LONG, BYVAL sFontName AS STRING)
              LOCAL hDc AS LONG, hFont AS LONG, tm AS TEXTMETRIC
              LISTBOX RESET hWnd, 102
             
              hDC = GetDc(hWnd)
             
              hFont = SelectObject(hDC, MakeFontEx(sFontName, 10, 0, 0, 0))
              GetTextMetrics hDC, tm
              IF tm.tmWeight < 500 And tm.tmItalic = 0 Then
                 LISTBOX ADD hWnd, 102, "Normal"
              END IF
              DeleteObject SelectObject(hDC, hFont)
             
              hFont = SelectObject(hDC, MakeFontEx(sFontName, 10, 0, 1, 0))
              GetTextMetrics hDC, tm
              IF tm.tmWeight < 500 And tm.tmItalic Then
                 LISTBOX ADD hWnd, 102, "Italic"
              END IF
              DeleteObject SelectObject(hDC, hFont)
             
              hFont = SelectObject(hDC, MakeFontEx(sFontName, 10, %FW_BOLD, 0, 0))
              GetTextMetrics hDC, tm
              IF tm.tmWeight  > 499 And tm.tmItalic = 0 Then
                 LISTBOX ADD hWnd, 102, "Bold"
              END IF
              DeleteObject SelectObject(hDC, hFont)
             
              hFont = SelectObject(hDC, MakeFontEx(sFontName, 10, %FW_BOLD, 1, 0))
              GetTextMetrics hDC, tm
              IF tm.tmWeight  > 499 And tm.tmItalic Then
                 LISTBOX ADD hWnd, 102, "Bold Italic"
              END IF
              DeleteObject SelectObject(hDC, hFont)
             
              ReleaseDc hWnd, hDC
             
            END SUB
             
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' Create a desirable font and return its handle. Original code by Dave Navarro
            ' NOTE: enhanced with proper enumeration of character set via EnumCharSet
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            FUNCTION MakeFontEx(BYVAL sFont AS STRING, BYVAL PointSize AS LONG, _
                                BYVAL fBold AS LONG, BYVAL fItalic AS LONG, BYVAL fUnderline AS LONG) AS LONG
              LOCAL hDC AS LONG, CharSet AS LONG, CyPixels AS LONG, lf AS LOGFONT
             
              hDC = GetDC(%HWND_DESKTOP)
                CyPixels  = GetDeviceCaps(hDC, %LOGPIXELSY)
                EnumFontFamilies hDC, BYVAL STRPTR(sFont), CODEPTR(EnumCharSet), BYVAL VARPTR(CharSet)
              ReleaseDC %HWND_DESKTOP, hDC
              PointSize = 0 - (PointSize * CyPixels) \ 72
             
              FUNCTION = CreateFont(PointSize, 0, _  'height, width(default=0)
                         0, 0, _                     'escapement(angle), orientation
                         fBold, _                    'weight (%FW_DONTCARE = 0, %FW_NORMAL = 400, %FW_BOLD = 700)
                         fItalic, _                  'Italic
                         fUnderline, _               'Underline
                         %FALSE, _                   'StrikeThru
                         CharSet, %OUT_TT_PRECIS, _
                         %CLIP_DEFAULT_PRECIS, %DEFAULT_QUALITY, _
                         %FF_DONTCARE , BYCOPY sFont)
             
            END FUNCTION
             
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' Enumerate fonts - here TrueType fonts only
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            FUNCTION EnumFontNames (elf AS ENUMLOGFONT, ntm AS NEWTEXTMETRIC, _
                                    BYVAL FontType AS LONG, hWnd AS LONG) AS LONG
              IF (FontType AND %TRUETYPE_FONTTYPE) THEN
                 COMBOBOX ADD hWnd, 101, elf.elfLogFont.lfFaceName
              END IF
              FUNCTION = 1
            END FUNCTION
             
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' Get type of character set - ansi, symbol.. a must for some fonts.
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            FUNCTION EnumCharSet (elf AS ENUMLOGFONT, ntm AS NEWTEXTMETRIC, _
                                  BYVAL FontType AS LONG, CharSet AS LONG) AS LONG
              CharSet = elf.elfLogFont.lfCharSet
              FUNCTION = 0 'break action - only needed charset
            END FUNCTION
            ------------------
            had to correct some comments..



            [This message has been edited by Borje Hagsten (edited October 15, 2001).]

            Comment


            • #7
              Borje --
              Can't understand, why do you create hFont.
              Code:
                 #Compile Exe
                 #Include "WIN32API.INC"
                 
                 Function EnumFontFamExProc(lpelfe As  ENUMLOGFONTEX, lpntme As NEWTEXTMETRICEX, ByVal FontType As Dword, lParam As String Ptr) As Long
                    @lParam = @lParam + lpelfe.elfLogFont.lfFaceName + " " + _
                              lpelfe.elfStyle + " Charset =" + Str$(lpelfe.elfLogFont.lfCharset) + _
                              " Weight = " + Str$(lpelfe.elfLogFont.lfWeight) + " " + _
                              " Italic =" + Str$(lpelfe.elfLogFont.lfItalic) + $CRLF
                    Function = 1
                 End Function
                
                Function PbMain
                   Dim hDC As Long, lf As LOGFONT, s As String
                   hDC = GetDC (0)
                   lf.lfFaceName = "Times New Roman"
                   lf.lfCharset = %DEFAULT_CHARSET
                   EnumFontFamiliesEx hDC, lf, CodePtr(EnumFontFamExProc), VarPtr(s), 0
                   ReleaseDC 0, hDC
                   MsgBox s
                End Function
              ------------------
              E-MAIL: [email protected]

              Comment


              • #8
                Because, enumeration only does not give 100% correct result for all fonts.
                Like, Abilene font says Weight 400 Italic 0, Bart font says Weight 700 and
                Italic 0, but nothing tells me what other styles they can have. Both can
                have all styles. Another font, Arial Rounded MT also says Weight 700 Italic 0,
                but can only be bold+italic. How to tell, without actually testing..?

                ------------------
                BTW, for eventual lurkers: EnumFontFamiliesEx does not work in Win95, so
                must test what system it is and use EnumFontFamilies in old system..
                (only extra is scripts - can usually do without those)


                [This message has been edited by Borje Hagsten (edited October 15, 2001).]

                Comment


                • #9
                  Borje --
                  1) I ran your code under Win2000 and received enough strange results.
                  2) Enumeration (at least, under Win2000) gives 100% correct results.
                  Another question, what means "correct" ...

                  Completely sure that windows simply takes information from font files' headers.
                  Three or four years ago I made own font (regular & bold).
                  I honestly marked Weight, but didn't worry about other fields.
                  If I marked a font as "Italic" (it could be), both (EnumFont & CreateFont) will accept a font as "Italic".

                  You talk - "Arial Rounded MT also says Weight 700 Italic 0, but can only be bold+italic".
                  Don't understand. Do you want to say that tm.tmItalic of created font will be non-zero ?
                  Guess, that it will be zero - Windows has no eyes



                  ------------------
                  E-MAIL: [email protected]

                  Comment

                  Working...
                  X