Note that there are some explanatory texts on larger screens.

plurals
  1. POCreating rotated text in WPF
    text
    copied!<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>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload