Option to Disable Checking of AltName from FontInfo | Font Substitution Issue in Words for Java version 19.2+

The following code snippets (adjusted to account for the API change in the second snippet) demonstrate a change of behavior between versions 19.1 and 19.2+ of Aspose Words for Java when converting DOCX to PDF. The behavior is the same in OS X and in Debian. In each case the same document is used and the only difference in our application is the version bump of Aspose Words for Java (and the necessary changes to use the new API).

// Version 19.1 (Works as expected; "Amplitude" substituted for "AmplitudeTF")
com.aspose.words.FontSettings settings = new com.aspose.words.FontSettings();
settings.setFontSubstitutes("Amplitude", "AmplitudeTF");

// Version 19.2+ (Fails; substitution rule is ignored and "Times New Roman" is used instead)
com.aspose.words.FontSettings settings = new com.aspose.words.FontSettings();
FontSubstitutionSettings subSettings = settings.getSubstitutionSettings();
subSettings.getTableSubstitution().setSubstitutes("Amplitude", "AmplitudeTF");

// Response of 19.1
Font substitutes: 'Amplitude' replaced with 'AmplitudeTF'.

// Response of 19.2+
Font 'Amplitude' has not been found. Using 'Times New Roman' font instead. Reason: alternative name from document.

As best I can tell this is the correct “port” of the older API (19.1 and earlier) to the new one (19.2+). If we are using your API correctly the regression in font behavior is annoying and erodes confidence in your product.

@workiva_rjackson,

To ensure a timely and accurate response, please ZIP and attach the following resources here for testing:

  • Your simplified input Word document you are getting this problem with
  • Aspose.Words for Java 19.10 generated output document showing the undesired behavior
  • Aspose.Words for Java 19.1 generated output document showing the correct behavior
  • The Font file
  • Please also create a standalone simple Java application (source code without compilation errors) that helps us to reproduce your current problem on our end and attach it here for testing. Please do not include Aspose.Words JAR files in it to reduce the file size.

As soon as you get these pieces of information ready, we will start investigation into your issue and provide you more information. Thanks for your cooperation.

Would you please first confirm that the code I originally posted is the correct transformation (port) when moving from 19.1 to 19.2+ to account for the API changes made in 19.2?

@workiva_rjackson,

When using the latest version of Aspose.Words for Java i.e. 19.10, the following code should produce the expected results:

com.aspose.words.FontSettings settings  = new com.aspose.words.FontSettings();
FontSubstitutionSettings subSettings = settings.getSubstitutionSettings();
subSettings.getTableSubstitution().addSubstitutes(
            "Amplitude",
             new String[] { "AmplitudeTF" });
doc.setFontSettings(settings);

Thank you. I’ve confirmed that either “addSubstitutes” or “setSubstitutes” yields the same (incorrect) behavior for this document and font. I have to determine whether or not I can share this particular font with your company before I can put together any additional materials.

In the interim it seems that to the extent you are able, it would be worth investigating on your end what changed in the API move from 19.1 to 19.2+ that altered table-based substitutions that might explain this kind of behavior. I don’t imagine that this is document or font specific and other customers may be experiencing similar issues.

@workiva_rjackson,

Please refer to the ‘Changes in Font Substitution Process and Public API’ section in the release notes page of Aspose.Words for Java 19.2.

Secondly, we need the resources mentioned in my previous post to be able to reproduce the exact same behavior on our end. It is safe to attach files in the forum. If you attach your documents/fonts here, only you and Aspose staff members can download them. We only need these resources for testing purposes.

Thank you for the link to the release notes. I did not realize that there was an explanation of the changes introduced in version 19.2.

I think I have identified the problem. In the new font resolution order step three (“3. AltName from FontInfo (if any)”) appears to be the problem.

Our document has this entry in its “fontTable.xml”:

<w:font w:name="Amplitude"><w:altName w:val="Times New Roman"/><w:panose1 w:val="00000000000000000000"/><w:charset w:val="00"/><w:family w:val="roman"/><w:notTrueType/><w:pitch w:val="default"/></w:font>

So the “altName” specifies “Times New Roman” which I should think is fine in itself. The new algorithm introduced in 19.2 however prevents any of the substitution logic from overriding the “altName” specified in the DOCX file.

If this is by design then we need a way of turning off step three to allow the font substitution rules to operate as before.

Thank you.

A post was split to a new topic: Provide Option to Turn Off Checking AltName from FontInfo

@workiva_rjackson,

We have logged your requirement in our issue tracking system. Your ticket number is WORDSNET-19524. We will further look into the details of this requirement and will keep you updated on the status of the linked issue. We apologize for any inconvenience.

@workiva_rjackson,

Regarding WORDSNET-19524, for this particular scenario, there is an easy workaround i.e. you can just clear the AltName field for each FontInfo in Document.FontInfos before the rendering. Could you please check and let us know if this will be acceptable for you? Thanks for your cooperation.

We will consider this approach and get back to you. Thank you.

@workiva_rjackson,

Sure, we will wait for your further input on this topic.

I’m not sure that overriding the “altName” (ECMA-376-1:2016 17.8.3.1) supplied in the DOCX file is what we will want to do. This seems to violate the intent of the specification:

When an application cannot locate a font using the primary name stored on the font attribute of the font element (§17.8.3.10), it should use each alternate name in term to attempt to locate the font, and use the first font for which is locates a match.

In this case the font cannot be matched by primary name due to the font matching algorithm in Aspose Words rather than the actual absence of the font.

We use your font substitution API (prior to 19.2) to correctly map the primary name so that Words can find it. Now that the matching algorithm changed in 19.2+ our hands are tied. Currently the algorithm is not robust enough to find the correct font on its own.

Font matching is not trivial so I don’t fault the current algorithm too much but without a way of helping it out (the way the substitution API used to work) Words tries to match the “altName” even though the primary name is technically available.

We would still like to see a way to allow this mapping to occur for proper recognition of the primary name.

@workiva_rjackson,

Thanks for the additional information. We have logged these details/concerns in our issue tracking system and will keep you posted on further updates.

@workiva_rjackson,

I am afraid, the reference to the specification you shared is not accurate. You are considering the font “technically available” while you set the substitute in the TableSubstitutionRule. But, I am afraid, it is wrong consideration. Aspose.Words’ documentation does not state that. And also, MS Word does not have such a feature. If you please open the problematic document in MS Word, then you will find that the font will be substituted.

At the moment, we will not be able to implement the requested feature. A workaround with changing the FontInfo.AltName in Aspose.Words DOM (document object model) is feasible. Please either empty the FontInfo.AltName or update it according to the substitutes table you use.

Font matching is a complex problem. It appears that MS Word uses a rather naive algorithm of its own (Word for Mac does not match our copy of AmplitudeTF for Amplitude (even though it is the same font)).

In this case https://fonts.adobe.com/fonts/amplitude (as supplied by https://store.typenetwork.com/foundry/fontbureau/fonts/amplitude) is internally named AmplitudeTF. If the document refers to “Amplitude” instead, Word will not find it.

What used to work with your API is that the font substitution algorithm would allow one to correct this naming inconsistency (and there are many other such examples in the font world) such that the proper font could be found.

It is frustrating that a breaking behavioral change was made in your API with no ability to retain the legacy behavior.

Given the diverse font world and the difficulties inherent in font matching it is disappointing that there is no mechanism in place that allows one to do this without modifying the content of the source file.

@workiva_rjackson,

Thank you for sharing more information on this topic. We have logged these details/concerns in our issue tracking system and will keep you posted on further updates.

@workiva_rjackson,

Please note that both Aspose.Words and MS Word do not support such feature as “internal font naming”. And as far as we know, most of the other text processors too. So, it is better to use the family name specified in the font file in the document. It will allow to get more consistent result of the document processing.

Also, there is no need to modify the content of the source file. FontInfo.AltName could be changed in Aspose.Words’ DOM (document object model) on the fly before rendering to PDF. And, the original values could be returned back if the document should be saved to word formats later. Though, updating FontInfo.AltName with the proper values may help in subsequent document processing. Hope, this helps.

Thank you for your consideration of the issue(s) here.

I can understand the font algorithm changes made in version 19.2+. If it were not for the limitations of (and the difficulties in) font matching, we wouldn’t have any problems with the new API.

With these changes the presence of AltName renders the substitution rules virtually useless unless the font specified by it is also “missing”.

Yes it is true that we can walk the DOM and erase those entries but that adds processing time that we were hoping to avoid.

Even if the intent of the substitution rule is to arbitrarily replace a font (rather than help the font matching logic locate the correct font), the presence of the AltName still short-circuits that logic.

I don’t want to go on forever on this topic so I will leave this here like this. The nature of the AltName as processed by your new algorithm is such that it would be nice if it could be turned off without having to walk the document prior to converting it to PDF.

Thank you for your time.

@workiva_rjackson,

Thanks for your further feedback on this topic which we have logged in our issue tracking system. So, the conclusion so far is that this scenario does not fit into MS Word font fetching/font substitution algorithm (as you also confirm it). That is why Aspose.Words currently does not provide an easy option to handle this scenario. But, your scenario could be fulfilled by working with Aspose.Words’ DOM. We are postponing the implementation of this new feature request for now (currently no estimates are available) and will keep you posted on further updates. We apologize for any inconvenience.