Drawing Text using FormattedText

FormattedText Class offers low-level method to manage drawing text in Windows Presentation Foundation (WPF). It processes text as graphical elements, instead of text in controls such as the TextBox and TextBlock, which implement the FlowDirection model or the XPS document model.

Basically, you should avoid using Formatted text and use the textblock, whenever possible. TextBlock honors the FlowDirection property and render the text properly. However, sometimes you need to do your own rendering of text. In this case you need to take care of the rendering of RightToLeft text.

This is the declaration of the FormattedText:

public FormattedText(

        string textToFormat,

        CultureInfo culture,

        FlowDirection flowDirection,

        Typeface typeface,

        double emSize,

        Brush foreground,

        NumberSubstitution numberSubstitution

)

 

I’m not going to discuss all the parameters of the FormattedText, let’s examine the RTL related paramaters:

Parameters

culture

Type: System.Globalization..::.CultureInfo

The specific culture of the text. It’s important set the culture to the valid entry , whether its’ the UICulture or you might default to non-RTL culture, if you need to opy-out of RTL behavior.

flowDirection

Type: System.Windows..::.FlowDirection

The direction the text is read. In the case of RTL text we need to set the value appropriately, because this influences how text is displayed. If we set it to FlowDirection=LeftToRight then the fullstop and the trailing neutral characters would be on the left of the text, and other wise it would be on the right of text. So Avoid setting it by default to FlowDirection=LeftToRight – and use the shell property “LayoutIsRightToLeft”to display the text appropriately.

For example as this sample:

      System.Windows.FlowDirection flow_direction;

      if (LayoutIsRightToLeft == true)

                flow_direction = FlowDirection.RightToLeft;

            else

                flow_direction = FlowDirection.LeftToRight;

numberSubstitution

Type: System.Windows.Media..::.NumberSubstitution

The number substitution behavior to apply to the text. Some RTL cultures use different digit shapes from those we are familiar with in the West. The below table illustrates some numbering systems used by diverse cultures.



Digits are used in calculations; therefore, it’s not practical to provide alternate Unicode code characters for each set of digit shapes. It’s the task of the OS and applications to render numbers correctly. The NumberSubstitution class provides functionality that allows different cultures to substitute the appropriate digit shapes at rendering time. This functionality is similar to the one used for providing font substitution and language dependent font rendering.

These are a list of possible NumberSubstitutionMethod

Member name

Description

AsCulture

Default. Specifies that the substitution method should be determined based on the number culture's DigitSubstitution property value.

Context

If the number culture is an Arabic or Farsi culture, specifies that the digits depend on the context. Either traditional or Latin digits are used depending on the nearest preceding strong character, or, if there is none, the text direction of the paragraph.

European

Specifies that code points 0x30-0x39 are always rendered as European digits, in which case, no number substitution is performed.

NativeNational

Specifies that numbers are rendered using the national digits for the number culture, as specified by the culture's NativeDigits property value.

Traditional

Specifies that numbers are rendered using the traditional digits for the number culture. For most cultures, this is the same as the DigitShapes..::.NativeNational enumeration value. However, using NativeNational can result in Latin digits for some Arabic cultures, whereas using Traditional results in Arabic digits for all Arabic cultures.

 

In most cases the default value is sufficient, however, you may need to display the digits as Western only and not as per the culture.

You will need more work. The “FormattedText” needs to be RightToLeft. This would display the mixed English and Arabic text properly and the full-stop would be displayed on the left side of text. Therefore you need to set the formattedText, FlowDirection to RightToLeft:

            flow_direction = FlowDirection.LeftToRight;

with this code:

           if (FlowDirection == FlowDirection.RightToLeft)

            {

                flow_direction = FlowDirection.RightToLeft;

            }

            else

            {

                flow_direction = FlowDirection.LeftToRight;

            }

The text is displayed to the left of the display area, instead of the right of the display area.  Therefore you should adjust the display origin to adjust the text display. You need to set the origin.X to a new origin and the transformation offset, for our case where FlowDirection.RightToLeft text. Another important effect of setting the FlowDirection parameter to RightToLeft is that the text is formatted to the left of the “origin”, instead of the right. The text is actually mirrored and not readable. So you need to apply a reflection transformation.

            if (FlowDirection == FlowDirection.RightToLeft)

            {

                double m11 = -1;

                double m22 = 1;

                double offsetX = formattedText.Width;

                double offsetY = 0;

                drawingContext.PushTransform(

                    new MatrixTransform(m11, 0, 0, m22, offsetX, offsetY));

                origin.X = formattedText.Width - x_margin;

            }

Don’t forget to remove the transformation, when you finish drawing text.

            if (FlowDirection == FlowDirection.RightToLeft)

                drawingContext.Pop();

 

I hope this was useful.