Current Status

As of Jan 2009.

Fonts are set with the "font-family" property, which can list multiple fonts separated by a comma.

Fop currently implements font-auto-selection on two levels:

  • A "fo:character" will automatically use the first font from the current list of font-families which contains the needed glyph
  • Normal text implementes a "word-by-word" stragey
  • font-selection "auto" in fop means word-by-word
  • character-by-character is not implemented, and the font-selection-stragey property is therefore ignored.

Word-by-Word

For each word, we go through every character and count how many characters are displayable in every font. The font which can display the most characters of the word is used. If multiple fonts can display the same number of characters, the first one of those listed in the font-famly property is used.

Examples

font-family="A, B" assume A can display xy, B can display yz.

xxx -> A
yyy -> A
zzz -> B

xxyy -> A
xxzz -> A
yyzz -> B

xxxz -> A
xxzz -> A
xzzz -> B

Implementation Rationale: This is due to the issues mentioned below, which do not allow an easy split of the alignment properties for each character.

Previous Information (2007)

This page gathers thoughts and information for implementing the font-selection-strategy property, or in other words, for supporting the evaluation of the font character by character in a text. Not every font supports every glyph, so if you specify font-family="Times, Symbol", FOP should, in the end, paint latin characters using Times and symbol characters with the Symbol font without the need of a work-around like an fo:wrapper or fo:character to get the right font.

Tasks

  • Do any necessary improvements to the font-family property.
  • FOText doesn't need to be touched.
  • Area tree and rendering doesn't need to be touched if TextLayoutManager produces separate areas per font.
  • Modify TextLayoutManager to determine the font for each character.
    • kerning may not be possible between two characters from different fonts.
    • A new area has to be created when the font changes.
    • Get the AlignmentContext handling right.

Definitions for the context of this page

  • character group: consecutive subset of characters for te FOText instance which are going to be painted with the same font.

Notes

I can see two possibilities for the implementation:

  1. Keep track of the font for each character in the TextLM. 2. Creating multiple TextLM instances from one FOText instance, splitting the text up by character groups. That would allow to avoid adding additional complexity to TextLM.

Chatting with Manuel over Skype, he told me to pay attention on the dependencies between LM instances over the AlignmentContext. Looking at this class shows that it takes values from a single font. So, the difficulty is not really keeping track of which font is used for each character. More difficult is to keep vertical alignment (baselines, ascenders etc.) under control. The situation with the dependencies needs to be improved which could make the implementation of the font-selection-strategy easier. Manuel suggests to follow the first approach above, unless those dependencies can be fixed in which case the second approach would work nicely.

There is a bug related to this issue, which has comments:

http://issues.apache.org/bugzilla/show_bug.cgi?id=39422

There is also a character-by-character font selection for JEuclid, which may serve as a reference. Please look at:

http://jeuclid.sourceforge.net/jeuclid-core/xref/net/sourceforge/jeuclid/elements/support/text/StringUtil.html#102

http://jeuclid.sourceforge.net/jeuclid-core/xref/net/sourceforge/jeuclid/elements/support/attributes/MathVariant.html#194

Alternative Implementation

Rationale

Given the above noted dependencies, there seems to be a third alternative: create multiple FOText instances in the FOTree, which would lead to two separate TextLMs being instantiated as a part of FOP's "natural" flow. The different, separate TextLMs will, by design, trigger the correct relative alignment, and maybe solve other of the above mentioned complications of implementing it in the layout-engine.

The FOTexts' characters are already looped over many times, so it does not really matter where in the process the check for the presence of a glyph in the current font is inserted. The only thing that would really need to change is the point where the fonts are first loaded: much sooner than is the case with the current implementation, but only from the point of view of a single FOP run. The argument here is that this matters very little in multi-session contexts where the fonts are handled by the FopFactory, and as such already loaded in 90% of the cases.

After looking a bit deeper, there seems to be a more fundamental problem in CommonFont.getFontState(): the method checks for fontState == null and if so, sets it to an instance of Font corresponding to the triplet using the first font-family in the list that is supported (see what FontInfo.fontLookup(String[],String,int) does). All subsequent times this method is called, the very same Font instance is returned. Through FontInfo one can create a new instance corresponding to a different triplet, by explicitly getting the next font-family through something like CommonFont.getFontFamily()[x]? This seems suboptimal somehow...

  • No labels