Font is not substituted

Hello,

we noticed a problem with fonts on a Linux machine. We are converting an html to pdf using Java. The default font for the html is Arial, there may be other true type fonts used in the html. If there are no expected true type fonts installed on the machine, then the font is selected randomly, and it results in either unreadable pdf document, or a 'Font embedding is prohibited because of font license restrictions" exception if the randomly chosen font cannot be embedded.

We tried to set a default font and substitute fonts but it seems that the substitutions are ignored. What is the correct way to implement font substitutions?

I am adding is a sample code below. I tried to make the “Noto Sans” font as a default one and as a font substitute for Arial. I tried to use the FontSettings.setFontSubstitutes to add a font substitution, and FontSettings.getFontSubstitutes(“Arial”) has a Noto Sans in the result list, but another font is used in the output pdf. I also found a sample code https://github.com/aspose-pdf/Aspose.PDF-for-Java/blob/master/Examples/src/main/java/com/aspose/pdf/examples/AsposePdfExamples/DocumentConversion/DefaultFontWhenSpecificFontMissing.java that uses the class " CustomSubst1 extends CustomFontSubstitutionBase" as can be seen in my sample, but its method trySubstitute is not invoked at all, and FontSettings.getFontSubstitutes(“Arial”) returns an empty list if FontSettings.setFontSubstitutes is not used.

public class FontTest
{
public static void main(String[] args) throws IOException
{
	FontTest asposeTest = new FontTest();
	asposeTest.loadAsposeLicense();
	FontSettings.setDefaultFontName("Noto Sans");
	FontSettings.setFontSubstitutes("Arial", new String[]{"Noto Sans"});
	String[] currentFontSubstitutes = FontSettings.getFontSubstitutes("Arial");
	CustomSubst1 subst1 = new CustomSubst1();
	FontRepository.getSubstitutions().add(subst1);

	for(String font : currentFontSubstitutes)
	{
		System.out.println("currentFontSubstitutes: " + font);
	}
	asposeTest.generateFromSimpleHtml();
}

private void generateFromSimpleHtml()
{
	HtmlLoadOptions options = new HtmlLoadOptions();
	InputStream is = FontTest.class.getResourceAsStream("/simple.html");
	Document document = new Document(is, options);
	document.FontSubstitution.add(new Document.FontSubstitutionHandler()
	{
		public void invoke(Font font, Font newFont)
		{
			// print substituted FontNames into console
			System.out.println("Warning: Font " + font.getFontName() + " was substituted with another font -> " + newFont.getFontName());
		}
	});
	document.save("/opt/arjanos/tmp/simple.pdf");
}

public void loadAsposeLicense()
{
	InputStream licenseStream = getClass().getClassLoader().getResourceAsStream("lt/test/Aspose.Pdf.lic");
	try(licenseStream)
	{
		License license = new License();
		license.setLicense(licenseStream);
	}
	catch(Exception e)
	{
		e.printStackTrace();
	}
}

private static class CustomSubst1 extends CustomFontSubstitutionBase
{
	public boolean trySubstitute(OriginalFontSpecification originalFontSpecification, /* out */com.aspose.pdf.Font[] substitutionFont)
	{
		System.out.println("TrySubstitute");
		// 1. substitute Arial font with TimesNewRoman font
		if("Arial".equals(originalFontSpecification.getOriginalFontName()))
		{
			System.out.println("Trying to substitute Arial");
			substitutionFont[0] = FontRepository.findFont("Noto Sans");
			return true;
		}
		else
		{
			return super.trySubstitute(originalFontSpecification, substitutionFont);
		}
		// 2. or substitute all the fonts with the MSGothic font
//			substitutionFont[0] = FontRepository.findFont("Noto Sans");
//			return true;
    	}
	}

}

simple.html:

<!DOCTYPE html>
	@media all {
		body {
			font-family: Arial, Helvetica, "Helvetica Neue", sans-serif;
		}
	}
</style>

</head>
<body>
<div>
	<p>Test</p>
</div>
</body>
</html>

What are we doing wrong? Or does font substitution work in some other way?

Thank you!

Arjana Bivainiene

@arjana

We need to perform further investigation against this scenario. We have logged an investigation ticket as PDFJAVA-40895 in our issue tracking system for the same purpose. We will look into its details and keep you posted with the status of its replication. Please be patient and spare us some time.

We are sorry for the inconvenience.

Hello,

when trying to update aspose to the newer version, I noticed that we were using FontSettings that is a class from an internal aspose package and it has been dropped. Is there a way to check what substitutions are used without using that class if Document.FontSubstitutionHandler is not invoked? What is the correct way to implement font substitutions?

Arjana

@arjana

There is no direct way to track the font substitution. However, following way can be used to implement font substitution:

FontRepository.getSubstitutions().add(new CustomPdfFontSubstitution());


private static class CustomPdfFontSubstitution extends CustomFontSubstitutionBase {
    @Override
    public boolean trySubstitute(OriginalFontSpecification originalFontSpecification, Font[] substitutionFont) {
        if (!originalFontSpecification.isEmbedded()) {
            try {
                Font fSrcInRepository = FontRepository.findFont(originalFontSpecification.getOriginalFontName());
                substitutionFont[0] = fSrcInRepository;
            } catch (FontNotFoundException e) {
                substitutionFont[0] = FontRepository.findFont("SimSun");
                System.out.println("Font " + originalFontSpecification.getOriginalFontName()
                        + " was substituted with another font -> " + substitutionFont[0].getFontName());
            }
            return true;
        } else {
            return super.trySubstitute(originalFontSpecification, substitutionFont);
        }
    }

Thank you, I am going to try to implement that. And is there a way to get the current default font?

@arjana

You can set and get fonts in a PDF document. Please check below articles:

Can you provide the solution for the same. I am facing same issue

@arsh01

We are afraid that the earlier logged ticket has not been yet resolved. However, we have recorded your concerns and will surely inform you once we make some progress towards its resolution. We apologize for the inconvenience.