回転したテキストを作成し、その画像を PNG ファイルに保存しようとしています。結果の PNG は、必要以上に大きくしないでください (または最小限のパディング)。回転がない限り機能していますが、テキストを回転させるとすぐに、ファイル内で切り取られます。RotateTransform の CenterX と CenterY を調整するか、TranslateTransform を作成することと関係があると確信していますが、それを正しく行う方法について何も見つけることができず、試行錯誤のテストが試行錯誤になりました-そしてフラストレーション。
私のサンプルコードは以下です。-45度だけでなく、任意の角度で機能するソリューションを探しています。
最後に、誰かがこれらの要件を満たす方法を知っていても、WPF ツールの代わりに「古いスタイル」の Graphics オブジェクトを使用すると言う場合、私はそれに対する解決策も受け入れます。
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;
}
アップデート
以下のいくつかの提案に基づいて、別の手法を試して GUI で実験することにしました。次のようなウィンドウを作成しました。
<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">
<Grid>
<Canvas Name="WorkCanvas" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-45"/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>This is a test</TextBlock>
</Canvas>
</Grid>
</Window>
ご覧のとおり、RotateTransform
と の両方を使用RenderTransformOrigin
し、結果は下の画像のようになります。そして、ご覧のとおり、テキストはの真ん中を通っていませんCanvas
。そして、それが私の全体的な問題のようです。テキストを回転させて正しく中央に配置する方法。
更新 2
今回は a のGrid
代わりに aを試してみることにしました。テキストをグリッドの中央に適切に配置できるようになりましたが、オブジェクトを使用できないため、実際の境界ボックスを測定できないようです。または のすべての測定値は、まったく回転していないかのように戻ります ( 、、および を参照)。回転したバウンディング ボックスのサイズを取得できない場合、PNG をクリップせずに保存することはできません。Canvas
FormattedText
TextBlock
Grid
ActualWidth
ActualHeight
DesiredSize
ああ、回転していないグリッドでテキストを回転させ、グリッド自体を回転させてみましたが、寸法を決定しようとすると、どちらも同じ結果になります。