In my earlier post, I mentioned the different consideration when dealing with rtl (or Bidi) text.  This time I’m going to post the sample with more in-depth discussion.

1)      I created a WPF Windows application: RTLApplication.  

2)      Created a CustomControl and called it RTL Control. This is the rendering code, and the highlight shows the differences to insure that RTL rendering is correct:

protected override void OnRender(DrawingContext drawingContext)

{

  // Draw a rectangle at the beginning

  Rect rect = new Rect(new Point(5, 5), new Size(25, 25));

  drawingContext.DrawRectangle(Brushes.Brown, (Pen)null, rect);

  // Prepare to draw the text

  String Text = "أهلاً Hello و مرحباً بكم.";

  Geometry textGeometry;

  Point origin = new Point();

  origin.Y = 0;

  int x_margin = 40;

  origin.X = x_margin;

  // Create the formatted text based on the properties set.

  FormattedText formattedText = new FormattedText(

      Text,CultureInfo.CurrentUICulture,

FlowDirection,

new Typeface("Arial"), 36, Brushes.Black);

   //Use a gradient to display red- green- and blue

   GradientStopCollection gsc = new GradientStopCollection();

   gsc.Add(new GradientStop(Colors.Red, 0));

   gsc.Add(new GradientStop(Colors.Green, 0.5));

   gsc.Add(new GradientStop(Colors.Blue, 1));

   // Build the geometry object that represents the text.

   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;

    }

    textGeometry = formattedText.BuildGeometry(origin);

    drawingContext.DrawGeometry(new LinearGradientBrush(gsc),

      new System.Windows.Media.Pen(Brushes.Blue, 0),

      textGeometry);

    if (FlowDirection == FlowDirection.RightToLeft)

      drawingContext.Pop();

    // Draw a circle at the end

    drawingContext.DrawEllipse(Brushes.DeepSkyBlue, (Pen)null,

new Point(formattedText.Width + x_margin + 10, 17), 12, 12);

  }

3)      Then I’ll go back to my MainWindow. I’ll add reference to my application to access my control:

xmlns:MyNamespace="clr-namespace:RTLApplication"

4)      Add a button to switch the FlowDirection:

if (FlowDirection == FlowDirection.RightToLeft)

FlowDirection = FlowDirection.LeftToRight;

else

FlowDirection = FlowDirection.RightToLeft;

5)      Finally run the application.

This is a complete application, enjoy!