WPF Sample for Drawing Text

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!

RTLApplication.zip