Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Knowing if a font exists

    Cinema 4D SDK
    windows python 2025
    2
    4
    82
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      datamilch
      last edited by

      hi there,

      i'd like to know if there is any way to know if the font i entered is valid / exists on the pc of the user.
      i can set the font 'Arial', but if i set a non existing font like 'Whatever', there will be a fallback to the default font. i tried to get some feedback, if this has happend, but i can not figure out how.

      font check 01.c4d

      this is my current code in a python generator:

      import c4d
      
      doc: c4d.documents.BaseDocument
      op: c4d.BaseObject
      
      def main() -> c4d.BaseObject:
      
          text = op[c4d.ID_USERDATA,2]
      
          # temp doc
          # ----------------------------------------------------------
          temp_doc: c4d.documents.BaseDocument = c4d.documents.BaseDocument()
          temp_doc.SetName("temp_doc")
          temp_null = c4d.BaseObject( c4d.Onull )
          temp_doc.InsertObject( temp_null )
      
          # create text spline
          # ----------------------------------------------------------
          text_spline = c4d.BaseObject( c4d.Osplinetext )
          text_spline[c4d.PRIM_TEXT_TEXT] = text
          text_spline[c4d.PRIM_TEXT_ALIGN] = 1
          text_spline[c4d.PRIM_TEXT_HEIGHT] = 1
          text_spline[c4d.PRIM_PLANE] = 2
      
          bc_font = c4d.BaseContainer()
          #bc_font.SetString(500, 'Arial')
          bc_font.SetString(500, 'Consolasssss')
          bc_font.SetInt32(502, 700) # weight
          fontdata = c4d.FontData()
          fontdata.SetFont( bc_font )
      
          text_spline[c4d.PRIM_TEXT_FONT] = fontdata
      
          # font check in temp doc
          # ----------------------------------------------------------
          text_spline.GetClone().InsertUnder( temp_null )
          temp_doc.ExecutePasses( c4d.threading.GeGetCurrentThread(), True, True, True, c4d.BUILDFLAGS_NONE )
      
          text_spline_2 = temp_null.GetDown()
          fontdata_check = text_spline_2[c4d.PRIM_TEXT_FONT]
          font_check = fontdata_check.GetFont()
          print( font_check[500] ) # will print the non existing font name, not the fallback default font
      
      
          return text_spline
      
      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @datamilch
        last edited by ferdinand

        Hey @datamilch,

        Thank you for reaching out to us. We recently had a very similar topic, where I gave an answer which is probably also relevant for you.

        In short, GetFontDescription is one of the ways to do this. What I would absolutely advise against, is browsing all font data to look for your font, because that can be very slow.

        The approach I showed in the linked topic requires that you can accurately predict the name of a font. E.g., predict that the font you are looking for will have the postscript name "ArialMT-Regular". This stands in contrast to just browsing all font data - for example via EnumerateFonts - and then checking one by one if one of the font labels contains the string "Arial". This latter approach will be very slow, because these browse functions all load the actual fonts to access their meta data.

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

        D 1 Reply Last reply Reply Quote 0
        • D
          datamilch @ferdinand
          last edited by

          hi @ferdinand exactly what i needed , thanks!
          the fontchek seems solid so far.

          did a bid of testing, the check with c4d.bitmaps.GeClipMap.GetFontDescription()
          seems only to work for the c4d.GE_FONT_NAME_POSTSCRIPT parameter. not with c4d.GE_FONT_NAME_FAMILY or c4d.GE_FONT_NAME_DISPLAY ... maybe because they could be ambiguous?

          then it was a bit unclear how the postscript names are constructed. i created a font-selector-user-data to print the ps-names of the selected font. these names could then be used to check if a font exists on another system. i just hope, these names are consistent across platfoms.

          the fontdata definiton still feels a bit unclear to me in respect to which values are needed or not. the ps-name alone will not work to define a fontdata. a single name in font[500] might work. ... in my test i used the bc returned by c4d.bitmaps.GeClipMap.GetFontDescription().

          here is some test code i used in a python generator:

          import c4d
          
          doc: c4d.documents.BaseDocument # The document the object `op` is contained in.
          op: c4d.BaseObject # The Python generator object holding this code.
          
          def main() -> c4d.BaseObject:
              
              fontdata = op[c4d.ID_USERDATA,1] # font selector data field
              font: c4d.BaseContainer = fontdata.GetFont()
              print( "==============================" )
              print( font[500] )
              print( font[501] )
              print( font[502] )
              print( font[503] )
              print( font[508],"  <- ps name" )
              print( font[509] )
              print( "------------" )
              
              # store the ps name for later
              font_ps_name = font[508]
              
              # we are testing the font, that we just selected in the user data - so it should always exist
              check_bc: c4d.BaseContainer | None = c4d.bitmaps.GeClipMap.GetFontDescription(font[508], c4d.GE_FONT_NAME_POSTSCRIPT)
              if not check_bc: print(f"508 nope")
              else:            print(f"508 exists" )
          
              print( "------------" )
              print( check_bc[500] )
              print( check_bc[502] )
              print( check_bc[503] )
              print( check_bc[504] )
              print( check_bc[509] )
              print( "------------" )
          
          
          
              # testing with spline text
              # --------------------------------------------------------
              
              # defing a font only with its ps-name will not work - yields default font   
              bc_font = c4d.BaseContainer()
              bc_font.SetString(508, font_ps_name)
              
              # using the data returned by GetFontDescription() works
              fontdata = c4d.FontData()
              fontdata.SetFont( check_bc )
              
              text_spline = c4d.BaseObject( c4d.Osplinetext )
              text_spline[c4d.PRIM_TEXT_TEXT] = "Text 0123"
              text_spline[c4d.PRIM_TEXT_FONT] = fontdata
              
              return text_spline
          
          1 Reply Last reply Reply Quote 0
          • D
            datamilch
            last edited by

            for my use case i will probably have a fallback solution with web-save or system fonts like this:

            import platform
            system_name = platform.system()
            if system_name == "Windows": font_name = "Consolas"
            elif system_name == "Darwin": font_name = "Menlo"
            elif system_name == "Linux": font_name = "DejaVu Sans Mono"
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post