Exception when Setting External Font Directory with Full Path under Linux in C#

Hi,

we run Aspose in a docker environment based on Ubuntu. We mount a directory with fonts into the container which we then configure in Aspose during start up.
The code only fails under Linux. Under Windows it worked fine (I tried we Console app without docker environment). Additionally it only fails when using the full path. Relative paths work good, so we have a workaround already. However I believe this bug still should be fixed.

The code handles Aspose.Words and Cells as well, only Aspose.Slides fails with an exception:

public static class FontUtils
{
    public static void SetFontDirectory(string fontDirectory)
    {
        SetFontDirectoryWord(fontDirectory);
        SetFontDirectoryCells(fontDirectory);
        SetFontDirectorySlides(fontDirectory); 
    }

    private static void SetFontDirectoryWord(string fontDirectory)
    {
        if (!Directory.Exists(fontDirectory))
        {
            return;
        }

        var externalFontSource = new Aspose.Words.Fonts.FolderFontSource(fontDirectory, true);
                true);

        // Sammeln der Font-Quellen
        var fontSources =
            new List<Aspose.Words.Fonts.FontSourceBase>(Aspose.Words.Fonts.FontSettings.DefaultInstance
                .GetFontsSources())
            {
                // Hinzufügen der eigenen Font-Quellen
                externalFontSource,
            };

        // Anwenden der neuen Font-Einstellungen
        Aspose.Words.Fonts.FontSettings.DefaultInstance.SetFontsSources(fontSources.ToArray());
    }

    private static void SetFontDirectoryCells(string fontDirectory)
    {
        if (!Directory.Exists(fontDirectory))
        {
            return;
        }

        var externalFontSource = new Aspose.Cells.FolderFontSource(fontDirectory, true);
        var fontSources = new List<Aspose.Cells.FontSourceBase>(Aspose.Cells.FontConfigs.GetFontSources())
        {
            // Hinzufügen der eigenen Font-Quellen
            externalFontSource,
        };

        // Anwenden der neuen Font-Einstellungen
        Aspose.Cells.FontConfigs.SetFontSources(fontSources.ToArray());
    }

    private static void SetFontDirectorySlides(string fontDirectory)
    {
        if (!Directory.Exists(fontDirectory))
        {
            return;
        }

        Aspose.Slides.FontsLoader.LoadExternalFonts(new[] { fontDirectory });
    }
}

Function is invoked by that code

public SlidesConverter(string fontDirectory, ILogger<SlidesConverter>? logger)
{
    Logger = logger;

    Logger?.LogInformation("Setting font directory, if existing");
    // fontDirectory equals "./fonts"
    FontUtils.SetFontDirectory(Path.GetFullPath(fontDirectory));
}

Exception from docker logs:

microservices-dev-documentConverterSlides-3  | Unhandled exception. System.ArgumentException: The value cannot be an empty string. (Parameter 'path')
microservices-dev-documentConverterSlides-3  |    at System.ArgumentException.ThrowNullOrEmptyException(String argument, String paramName)
microservices-dev-documentConverterSlides-3  |    at System.IO.Path.GetFullPath(String path)
microservices-dev-documentConverterSlides-3  |    at ♥▬♣tring ☻)
microservices-dev-documentConverterSlides-3  |    at Aspose.Slides.FontsLoader.☻(String[] ☻)
microservices-dev-documentConverterSlides-3  |    at Aspose.Slides.FontsLoader.LoadExternalFonts(String[] directories)
microservices-dev-documentConverterSlides-3  |    at CS.Converter.Office.Wrapper.Utils.FontUtils.SetFontDirectorySlides(String fontDirectory) in /src/CS.Converter.Office.Wrapper/Utils/FontUtils.cs:line 73
microservices-dev-documentConverterSlides-3  |    at CS.Converter.Office.Wrapper.Utils.FontUtils.SetFontDirectory(String fontDirectory) in /src/CS.Converter.Office.Wrapper/Utils/FontUtils.cs:line 13
microservices-dev-documentConverterSlides-3  |    at CS.Service.Rendering.DocumentConverter.Slides.Services.Documents.SlidesConverter..ctor(ILogger`1 logger) in /src/CS.Service.Rendering.DocumentConverter.Slides/Services/Documents/SlidesConverter.cs:line 19
microservices-dev-documentConverterSlides-3  |    at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
microservices-dev-documentConverterSlides-3  |    at System.Reflection.ConstructorInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
microservices-dev-documentConverterSlides-3  |    at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
microservices-dev-documentConverterSlides-3  |    at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
microservices-dev-documentConverterSlides-3  |    at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
microservices-dev-documentConverterSlides-3  |    at CS.Service.Rendering.DocumentConverter.Slides.Program.MainAsync(String[] args) in /src/CS.Service.Rendering.DocumentConverter.Slides/Program.cs:line 30
microservices-dev-documentConverterSlides-3  |    at CS.Service.Rendering.DocumentConverter.Slides.Program.MainAsync(String[] args) in /src/CS.Service.Rendering.DocumentConverter.Slides/Program.cs:line 42
microservices-dev-documentConverterSlides-3  |    at CS.Service.Rendering.DocumentConverter.Slides.Program.Main(String[] args) in /src/CS.Service.Rendering.DocumentConverter.Slides/Program.cs:line 15

Also tried putting the path directly and can confirm it works without calling Path.GetFullPath("./fonts") but passing the string directly.

@Serraniel,
Thank you for contacting support.

Please carefully check that you are not passing an empty string to the fontDirectory parameter, and use the latest version of Aspose.Slides for .NET if it is possible. If it is not the case, please share the dockerfile you used.

Hello,

thanks for your reply. I managed to figure out the cause of the exception was because I also added the system font directory (is this even neccessary? I wasn´t sure if it setting a custom directory would override system fonts or not), however the environment variable was empty. I fixed this by checking that path as well.

However I still run over the issue, that the fonts are not used in the generated PDF document.
Please see the attached zip which contains test project with dockerfile (I just copied from a docker file which also uses Aspose.Words and Aspose.Cells, so there may be some overhead) and docker-compose.yml to mount the folders.

FontUtils sets the fonts directory. The found ttf files are printed to console as well, so you can see the path is correct.

In files folder there is an example presentation using the example font, the PDF words generates and the PDF Aspose in the docker environment generates.

example.zip (385.8 KB)

2023-05-26_10-42-09.png (10.6 KB)
2023-05-26_10-31-41.png (36.8 KB)
2023-05-26_10-32-15.png (39.0 KB)

Thanks for your help,
Daniel

@Serraniel,
Thank you for the details.

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): SLIDESNET-44024

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.