Free Support Forum - aspose.com

Loading External Font(s) Not Working

We are using the Slides SDK for .NET v18.7.0 (though we are running on .NET Core inside a container).

The problem we are experiencing is that no matter where. or how we try to load custom font(s), we still receive the substitution warning

Font will be substituted from Calibri Light to {Arial,MS Gothic,Gulim,Arial Unicode}

We have verified that the file for this font is present in all of these directories and available when loaded, however we are still receiving this error.

We have attempted to use both the following methods for loading fonts

FontsLoader.LoadExternalFont(...)
FontsLoader.LoadExternalFonts(...)

We have a custom font folder that we are copying all the fonts from into the following folders

/usr/share/fonts
/usr/local/share/fonts
fonts
/root/.fonts

We have tried clearing the font cache before all fonts are loaded, as well as before each as well, with no luck.

   using System;
   using Aspose.Slides;
   using System.Drawing;
   using System.Collections.Generic;
   using System.IO;
   using System.Linq;
   using System.Threading;
   using Aspose.Slides.Export;
   using System.Threading.Tasks;
   using Aspose.Slides.Warnings;

  namespace converter
   {
       class Program
       {
           static void Main(string[] args)
           {
               Console.WriteLine("Running conversion...");

              string fileName = "test-a.pptx";

              var fontDirs = FontsLoader.GetFontFolders();
              foreach(var folder in fontDirs) 
              {
                  var files = Directory.EnumerateFiles(folder);
                  foreach(var file in files)
                  {
                      FontsLoader.ClearCache();
                      var bytes = File.ReadAllBytes(file);
                      FontsLoader.LoadExternalFont(bytes);           
                  }
              }



              try
              {
                  LoadOptions lo = new LoadOptions();

                  lo.WarningCallback=new HandleFontsWarnings();
                  
                  using (Presentation pres = new Presentation(fileName, lo))
                  {
                      for(var i = 0; i < pres.Slides.Count; i++ ) 
                      {
                          ISlide sld = pres.Slides[i];
                          string imageName = String.Format("slide-{0}.jpg", i);

                          // Create a full scale image
                          Bitmap bmp = sld.GetThumbnail(1f, 1f);
                      
                          // Save the image to disk in PNG format
                          bmp.Save(imageName, System.Drawing.Imaging.ImageFormat.Png);

                          Console.WriteLine("Done converting image {0}", imageName);
                      }
                  }

                  Console.WriteLine("Done...");
              }
              catch(Exception e)
              {
                  Console.WriteLine(e.Message);
              }
              

              Thread.Sleep(Timeout.Infinite);
          }
      }
      class HandleFontsWarnings : IWarningCallback
      {

          public ReturnAction Warning(IWarningInfo warning)
          {
              Console.WriteLine(warning.WarningType); // 1 - WarningType.DataLoss
              Console.WriteLine(warning.Description); // "Font will be substituted from X to Y"
              return ReturnAction.Continue;
          }
      }
  }

I have attached a screenshot here (13.9 KB) showing the contents of one of the folders we load fonts from contains the font that is being substituted.

@commercialtribe,

I have observed the issue shared by you. It seems that your fonts folder is not properly loaded. There seems one little mistake in your code that you are clearing cache on every loop iteration before loading font directory. This way, you will only be keeping the last font of fontDirs index in your loaded fonts list. You can try commenting the following statement.

//comment following line
FontsLoader.ClearCache(); 

Moreover, the following statement only gives you list of fonts folder that have been loaded externally. You are calling this line wrongly in your sample as you have never loaded the fonts externally before calling this.

FontsLoader.GetFontFolders

You need to call following to load the font directories or specific fonts.

FontsLoader.LoadExternalFont(directory name or font bytes)

I hope the shared elaboration will be helpful.

A couple things I wanted to follow up on.

  1. Though the copied example shows the FontsLoader.ClearCache() on every loop iteration, we also previously attempted this prior to the loop as well. I will comment this out for the purpose of the following statements.

  2. The call to GetFontFolders() was returning the following list of directories…

    /usr/share/fonts
    /usr/local/share/fonts
    fonts
    /root/.fonts

During our build process, we are moving all of our fonts to each of these folders in an attempt for them to be discovered. I am not sure why we would load the fonts before calling GetFontFolders() as I am not sure what value that would provide. By the time we cal GetFontFolders(), our custom fonts are already in these directories.

  1. We attempted to use both FontsLoader.LoadExternalFonts() and loaded all these directories (and even another custom one we created) as well as FontsLoaders.LoadExternalFont() where we load each of the font files that we moved into these directories during build time.

None of these suggestions work…

Here is a more simplified example that we have tried and is also based almost directly on your documentation that does not work as well

static void Main(string[] args)
{
    Console.WriteLine("Running conversion...");

    string fileName = "test-a.pptx";

    var fontDir = "/path/to/custom/font/dir";

    var bytes = File.ReadAllBytes(file);

    FontsLoader.LoadExternalFonts(new string[]{fontDir});

    LoadOptions lo = new LoadOptions();

    lo.WarningCallback=new HandleFontsWarnings();
    
    using (Presentation pres = new Presentation(fileName, lo))
    {
        for(var i = 0; i < pres.Slides.Count; i++ ) 
        {
            ISlide sld = pres.Slides[i];
            string imageName = String.Format("slide-{0}.jpg", i);

            // Create a full scale image
            Bitmap bmp = sld.GetThumbnail(1f, 1f);
        
            // Save the image to disk in PNG format
            bmp.Save(imageName, System.Drawing.Imaging.ImageFormat.Png);

            Console.WriteLine("Done converting image {0}", imageName);
        }
    }
}

@commercialtribe,

Thank you for sharing the feedback. I have observed the information shared by you and request you to please provide the source presentation, Operating System details, Warning Callback trace in the form of output and generated output. We will use that information to investigate that further on our end. Please also specify the .NET Framework used. If possible, please provide the working sample project that we may use as reference.