Search code examples
fontsarabicdirectwrite

What typography setting is enabling Arabic "end" contextual forms at the end of lines wrapped in the middle of a word?


The following is laid out using an IDWriteTextLayout with dimensions 250x100. It simply contains 150 of the Arabic letter U+062A, with no spaces, using Calibri 24 (normal weight/style/stretch). The blue box shows the 250x100 layout area (the text overflows because I haven't set a trimming mode), the green box shows the laid out dimensions from the metrics, the pink box takes overhang metrics into account, and the grey boxes are from hit testing every character.

Not using any IDWriteTypography object.

Compare that to the following, where the only difference is that I've called IDWriteTextLayout::SetTypography and passed an empty IDWriteTypography object which was created by IDWriteFactory::CreateTypography and not modified at all.

Using an empty IDWriteTypography object.

Just looking at the appearance of the text, the last character on each line has assumed the Arabic "end" contextual form, which I believe is generally applied to the last character of a word (I don't know Arabic). In what I can only currently guess is a bug in DirectWrite, this has caused the text to actually hang outside both the specified layout area and the area returned by the metrics (the amount that it hangs outside the box seems equal to the extra width added by the change in contextual form).

From other experimentation, it seems that setting an empty IDWriteTypography object has the effect of disabling every possible font feature. So by disabling some typographical font feature which is apparently enabled by default, I've caused it to use the "end" form for characters at the end of lines, even if they're not at the end of words. Which font feature is controlling this behavior? I've tried tweaking the IDWriteTypography instance to enable (set its value to 1) every font feature listed in the documentation one at a time, and none of them result in the old appearance. Is the relevant feature one of the ones that actually uses an integral value rather than a boolean?

My goal here is to use an IDWriteTypography object on my IDWriteTextLayout for unrelated reasons, but avoid having the text hang outside of the layout area. So alternatively, is there some other way to work around that behavior?


Solution

  • You've got a lot going on here that makes me think this is somewhat of an XY Problem, but I can at least answer the specific question about which font feature controls word-final forms in Arabic. That is the "Terminal Forms", or 'fina' feature. It is an essential, non-optional feature of Arabic script and is not only "on by default", it is not possible to disable it with Windows text layout. That is why you don't see anything in the DWRITE_FONT_FEATURE_TAG enumeration corresponding to it.

    To my initial point about XY Problem: do you realistically expect cases like this (a single repeating caracter occupying the entire contents of a text box)? Perhaps you'd be better served testing with more realistic text: for example, the output from a multilingual "lorem-ipsum" generator? While DWrite is pretty robust, I very much doubt that its designers sought to achieve perfection with extreme cases such as this. You can probably find lots of oddball cases that are DWrite "bugs", using totally unrealistic text.