title: Creating rotated text in WPF
body: <p>I am trying to create some rotated text and save that image to a PNG file. The resulting PNG should be no larger than needed (or minimal padding). I have it working as long as there is <em>no rotation</em>, but as soon as I rotate the text, it is getting clipped off in the file. I am sure it has something to do with adjusting the either the CenterX and CenterY of the RotateTransform or creating a TranslateTransform, but I can't find anything on how to do it correctly and my trial-and-error testing has turned into trial-and-<em>frustration</em>.</p>
  
  <p>My sample code is below. I looking for a solution that would work with an arbitrary angle and not just -45 degrees.</p>
  
  <p>Finally, if someone knows how to meet these requirements, but say using an "old style" Graphics object instead of WPF tools, I am open to that solution to that too.</p>
  
  <pre><code>private static void CreateImageFile()
  {
      FormattedText ft;
      Geometry textBox;
      string fontName;
      Typeface face;
      DrawingVisual viz;
      RotateTransform rt;
      TranslateTransform tt;
      Rect rect;
      RenderTargetBitmap bmp;
      PngBitmapEncoder encoder;
  
      ft = CreateText("Lorem ipsum dolor sit amet, consectetur adipisicing" + Environment.NewLine + "elit, sed do eiusmod tempor", "Verdana", 12, false, false);
      textBox = ft.BuildHighlightGeometry(new Point());
  
      fontName = "Arial";
      face = new Typeface(fontName);
  
      // now create the visual we'll draw them to
      viz = new DrawingVisual();
      rt = new RotateTransform() { Angle = -45 };
      rect = rt.TransformBounds(ft.BuildHighlightGeometry(new Point(0, 0)).Bounds);
  
      using (DrawingContext dc = viz.RenderOpen())
      {
          dc.PushTransform(rt);
          dc.DrawText(ft, new Point(0, 0));
          dc.Pop();
      }
  
      bmp = new RenderTargetBitmap((int)rect.Width, (int)rect.Height, 96, 96, PixelFormats.Pbgra32);
      bmp.Render(viz);
  
      encoder = new PngBitmapEncoder();
      encoder.Frames.Add(BitmapFrame.Create(bmp));
      using (FileStream file = new FileStream("TextImage.png", FileMode.Create))
          encoder.Save(file);
  }
  
  private static FormattedText CreateText(string text, string typeface, double fontSize, bool bold, bool italic)
  {
      FontStyle fontStyle = FontStyles.Normal;
      FontWeight fontWeight = FontWeights.Medium;
  
      if (bold == true) fontWeight = FontWeights.Bold;
      if (italic == true) fontStyle = FontStyles.Italic;
  
      // Create the formatted text based on the properties set.
      FormattedText formattedText = new FormattedText(
          text,
          CultureInfo.CurrentCulture,
          FlowDirection.LeftToRight,
          new Typeface(new FontFamily(typeface),
              fontStyle,
              fontWeight,
              FontStretches.Normal),
          fontSize,
          Brushes.Black, // This brush does not matter since we use the geometry of the text. 
          null,
          TextFormattingMode.Display
          );
  
      return formattedText;
  }
  </code></pre>
  
  <hr>
  
  <h2>Update</h2>
  
  <p>Based upon some of the suggestions below, I decided to try a different tack and experiment in the GUI. I created a window like this:</p>
  
  <pre><code>&lt;Window x:Class="WpfApplication1.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="MainWindow" Height="160" Width="160" Loaded="Window_Loaded"&gt;
      &lt;Grid&gt;
          &lt;Canvas Name="WorkCanvas" HorizontalAlignment="Center" VerticalAlignment="Center"&gt;
              &lt;TextBlock RenderTransformOrigin="0.5,0.5"&gt;
                  &lt;TextBlock.RenderTransform&gt;
                      &lt;TransformGroup&gt;
                          &lt;ScaleTransform/&gt;
                          &lt;SkewTransform/&gt;
                          &lt;RotateTransform Angle="-45"/&gt;
                          &lt;TranslateTransform/&gt;
                      &lt;/TransformGroup&gt;
                  &lt;/TextBlock.RenderTransform&gt;This is a test&lt;/TextBlock&gt;
          &lt;/Canvas&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>As you can see, it uses both the <code>RotateTransform</code> and the suggested <code>RenderTransformOrigin</code>, and the result is like the image below. And, as you can see, the text does <strong>not</strong> go through the middle of the <code>Canvas</code>. And <strong>that</strong> seems to be my entire problem. How to rotate the text <strong>and</strong> get it correctly centered.</p>
  
  <p><img src="https://i.imgur.com/S7FUt.png" alt="Example"></p>
  
  <hr>
  
  <h2>Update 2</h2>
  
  <p>I decided to try a <code>Grid</code> instead of a <code>Canvas</code> this time and I can now get the text properly centered in the grid, but since I can't use a <code>FormattedText</code> object, I can't seem to measure the actual bounding box. All measurements of the <code>TextBlock</code> or the <code>Grid</code> come back as if it was not rotated at all (looking at <code>ActualWidth</code>, <code>ActualHeight</code>, and <code>DesiredSize</code>). If I can't get the rotated bounding box size, I can't save the PNG without it getting clipped. </p>
  
  <p>Oh, and I tried rotating the text in an unrotated grid and rotating the grid itself, both give the same results when trying to determine the dimensions.</p>